您的位置:首页 > 数据库

ADO.NET与ORM的比较(3)Linq to SQL实现CRUD

2013-05-19 00:28 561 查看
ADO.NET与ORM的比较(3)Linq to SQL实现CRUD 2010-04-11 22:23:05
标签:.NET Framework
晒文章
ORM
Linq

ASP.NET
原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。http://zhoufoxcn.blog.51cto.com/792419/293966

说明:个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hibernate,除了在学习基础知识的时候被告知可以使用JDBC操作数据库之外,大量的书籍中都是讲述使用Hibernate这个ORM工具来操作数据。在.NET中操作数据库的方式有多种,除了最直接的方式就是使用ADO.NET之外,还可以使用NHibernate这个Hibernate在.NET中的实现ORM,如果你对第三方的ORM持怀疑态度,你还可以使用来自微软的实现、根正苗红的Linq或者EntityFramework。

 大部分从早期就开始使用.NET开发的程序员可能对ADO.NET有种迷恋,使用ADO.NET可以充分将我们早期的SQL知识发挥得淋漓尽致,并且出于对性能的考虑,有些人对.NET中的ORM还保持一种观望态度,包括我自己也是这种态度。不过即使在实际开发中不用,并不代表我们不能去了解和比较这些技术,任何事物的出现和消亡总有其原因的,我们可以了解它们的优点和长处。所以本人抽出了几个周末的时间分别用ADO.NET、NHibernate、Linq和EntityFramework来实现对数据库单表数据的创建、读取、更新和删除操作,也就是所谓的CRUD(C:Create/R:Read/U:Update/D:Delete)。

 通过实现相同功能的比较,大家自己判断那种方式更适合自己。需要说明的是,如果在VS2008中使用EntityFramework就需要安装VS2008SP1。

 语言集成查询 (LINQ) 是 Visual Studio 2008 中的一组功能,可为 C# 和 Visual Basic 语言语法提供强大的查询功能。LINQ 引入了标准的、易于学习的查询和更新数据模式,可以对其技术进行扩展以支持几乎任何类型的数据存储。Visual Studio 2008 包含 LINQ 提供程序的程序集,这些程序集支持将 LINQ 与 .NET Framework 集合、SQL Server 数据库、ADO.NET 数据集和 XML 文档一起使用。

 在本篇讲述利用Linq实现对数据库的CRUD功能,也就是Linq to SQL,需要说明的是Linq to SQL只支持SQL Server数据库,Linq to SQL只是Linq的一部分功能。

 用Linq to SQL来操作数据库确实比使用NHibernate在操作上要方便得多,通过下面的操作读者也会体会得到,毕竟这个是微软官方的东东,微微支持的力度自然要大些。
 一、准备

 首先,向项目中添加Linq To SQL的类,如下图所示:

 


 在名称一栏中填写较友好的名字之后,然后项目中就会增加一个后缀为dbml的文件,双击这个文件就会进入设计视图,如下图所示:

 


 在服务器资源管理中找到相应的数据库连接,依次点开之后就可以将数据库中的表拖到dbml设计器上。如果读者界面上没有服务器资源管理器可以使用CTRL+ALT+S组合键将其调出来。如果没有数据库连接,可以按照下面的步骤进行,在服务器资源管理器中的“数据连接”——“添加连接”,出现如下界面:

 

 


 在上面的界面中依次填写好数据库、用户名和密码及要连接的库名之后,点击确定,这样在服务器资源管理器中就增加了一个数据库连接,展开之后如下图所示:

 


 拖拽一个表到dbml上就会自动生成这个表的实体类,如下图所示:

 


 也许有人会思考这个类的定义在哪里,可以告诉你的是这个类的定义在这个dbml文件对应的cs文件中(dbml文件名.designer.cs这种形式),如下图所示:

 


 有些这些之后我们就可以动手编码实现对数据库进行CRUD操作了。

 二、编码
 由于在dbml文件中已经存在了DataContext和UserInfo表对应的UserInfo实体类,所以我们仅仅需要编写对数据库操作的类就可以了。编写的代码如下:



using System;



using System.Collections.Generic;



using System.Linq;



using System.Text;



using System.Data.SqlClient;



using System.Data.Linq;



using System.Configuration;


    



namespace LinqDemo


{


        
/// <summary>


        
/// 说明:这个类是为了演示.NET中的Linq to SQL的用法


        
/// 作者:周公(周金桥)


        
/// 日期:2010-03-01


        
/// </summary>


        
public class LinqCRUD


         {


                
/// <summary>


                
/// 统计用户总数


                
/// </summary>


                
/// <returns></returns>


                
public int Count()


                 {


方法一#region
方法一


                        
//使用SqlConnection来实例化DataContext对象


                         SqlConnection connection =
new SqlConnection(ConfigurationManager.ConnectionStrings["LinqDemo.Properties.Settings.AspNetStudyConnectionString"].ConnectionString);


                         DataContext context =
new DataContext(connection);


                         IEnumerable<int> collection = context.ExecuteQuery<int>("select
count(1) from UserInfo");


                        
int count = collection.ElementAt<int>(0);


                        
return count;


                         #endregion


    


方法二#region
方法二


                        
//UserInfoDataClassesDataContext context = new UserInfoDataClassesDataContext();


                        
////return context.UserInfo.Count<UserInfo>(item => item.Age > 23);//带条件统计


                        
//return context.UserInfo.Count<UserInfo>();


                         #endregion


                 }


                
/// <summary>


                
/// 创建用户


                
/// </summary>


                
/// <param name="info">用户实体</param>


                
/// <returns></returns>


                
public void Create(UserInfo info)


                 {


                         UserInfoDataClassesDataContext context =
new UserInfoDataClassesDataContext();


                         context.UserInfo.InsertOnSubmit(info);


                         context.SubmitChanges();


                 }


                
/// <summary>


                
/// 读取用户信息


                
/// </summary>


                
/// <param name="userId">用户编号</param>


                
/// <returns></returns>


                
public UserInfo Read(int userId)


                 {


                         UserInfoDataClassesDataContext context =
new UserInfoDataClassesDataContext();


                         context.Log = Console.Out;


                         var query = from item
in context.UserInfo


                                                 where item.UserID == userId


                                                 select item;


                        
return query.First<UserInfo>();


                 }


                
/// <summary>


                
/// 更新用户信息


                
/// </summary>


                
/// <param name="info">用户实体</param>


                
/// <returns></returns>


                
public void Update(UserInfo info)


                 {


                         UserInfoDataClassesDataContext context =
new UserInfoDataClassesDataContext();


                         UserInfo ui = context.UserInfo.First<UserInfo>(item => item.UserID == info.UserID);


                         ui.Age = info.Age;


                         ui.Email = info.Email;


                         ui.Mobile = info.Mobile;


                         ui.Phone = info.Phone;


                         ui.RealName = info.RealName;


                         ui.Sex = info.Sex;


                         ui.UserName = info.UserName;


                         context.SubmitChanges();


                 }


                
/// <summary>


                
/// 删除用户


                
/// </summary>


                
/// <param name="userId">用户编号</param>


                
/// <returns></returns>


                
public void Delete(int userId)


                 {


方法一#region
方法一


                        
//UserInfoDataClassesDataContext context = new UserInfoDataClassesDataContext();


                        
//context.ExecuteCommand("delete from UserInfo where UserId=" + userId);


                         #endregion


方法二#region
方法二


                         UserInfoDataClassesDataContext context =
new UserInfoDataClassesDataContext();


                         UserInfo ui = context.UserInfo.First<UserInfo>(item => item.UserID == userId);


                         context.UserInfo.DeleteOnSubmit(ui);


                         context.SubmitChanges();


                         #endregion


                 }


    


                
/// <summary>


                
/// 删除用户


                
/// </summary>


                
/// <param name="userId">用户实体</param>


                
/// <returns></returns>


                
public void Delete(UserInfo info)


                 {


                         UserInfoDataClassesDataContext context =
new UserInfoDataClassesDataContext();


                         var userList = from Users    


                                                            in context.UserInfo


                                                            where Users.UserID == info.UserID    


                                                            select Users;


                        
foreach (var user
in userList)


                         {


                                 context.UserInfo.DeleteOnSubmit(user);


                         }


                        
//context.UserInfo.DeleteOnSubmit(userList.First<UserInfo>());


                        
//注意下面的写法是错误的


                        // context.UserInfo.DeleteOnSubmit(info);


                         context.SubmitChanges();


                 }


    


                
/// <summary>


                
/// 获取用户表中编号最大的用户


                
/// </summary>


                
/// <returns></returns>


                
public int GetMaxUserId()


                 {


                         UserInfoDataClassesDataContext context =
new UserInfoDataClassesDataContext();


                        
int userId=context.UserInfo.Max<UserInfo>(item => item.UserID);


                        
return userId;


                 }


         }


}

 说明,在上面的代码中每个方法的第一句都是实例化一个叫UserInfoDataClassesDataContext的类,这个类我们并没有编写,但是奇怪的是上面的代码居然能编译通过,这是为什么呢?原来秘密还是在那个dbml文件中,这个类在dbml的设计文件中的定义如下:


[System.Data.Linq.Mapping.DatabaseAttribute(Name="AspNetStudy")]



public partial class UserInfoDataClassesDataContext : System.Data.Linq.DataContext


{



//.....省略其它代码


}

 可以看出UserInfoDataClassesDataContext是继承DataContext的,这个DataContext在MSDN中的定义为:

 DataContext 是通过数据库连接映射的所有实体的源。它会跟踪您对所有检索到的实体所做的更改,并且保留一个“标识缓存”,该缓存确保使用同一对象实例表示多次检索到的实体。

 也就是我们用DataContext来与数据库进行交互,DataContext会根据上下文环境来决定如何与数据库交互,正因为如此,所以我们用Linq to SQL的代码才如此简单!

 三、单元测试代码



using System;



using System.Collections.Generic;



using System.Linq;



using System.Text;



using NUnit.Framework;



using LinqDemo;


    



namespace NUnitTest


{


         [TestFixture]


        
public class LinqTest


         {


                
private LinqCRUD instance =
null;


                 [SetUp]


                
public void Initialize()


                 {


                         instance =
new LinqCRUD();


                 }


                 [Test]


                
/// <summary>


                
/// 统计用户总数


                
/// </summary>


                
/// <returns></returns>


                
public void Count()


                 {


                         Assert.Greater(instance.Count(), 0);


                 }


                 [Test]


                
/// <summary>


                
/// 创建用户


                
/// </summary>


                
/// <param name="info">用户实体</param>


                
/// <returns></returns>


                
public void Create()


                 {


                         UserInfo info =
new UserInfo()


                         {


                                 Age = 12,


                                 Email =
"zzz@ccav.com",


                                 Mobile =
"13812345678",


                                 Phone =
"01012345678",


                                 RealName =
"测试" + DateTime.Now.Millisecond.ToString(),


                                 Sex =
true,


                                 UserName =
"zhoufoxcn" + DateTime.Now.Millisecond.ToString()


                         };


                         instance.Create(info);


                 }


                 [Test]


                
/// <summary>


                
/// 读取用户信息


                
/// </summary>


                
/// <param name="userId">用户编号</param>


                
/// <returns></returns>


                
public void Read()


                 {


                         UserInfo info = instance.Read(1);


                         Assert.NotNull(info);


                 }


                 [Test]


                
/// <summary>


                
/// 更新用户信息


                
/// </summary>


                
/// <param name="info">用户实体</param>


                
/// <returns></returns>


                
public void Update()


                 {


                         UserInfo info = instance.Read(1);


                         info.RealName =
"测试" + DateTime.Now.Millisecond.ToString();


                         instance.Update(info);


                 }


                 [Test]


                
/// <summary>


                
/// 删除用户


                
/// </summary>


                
/// <param name="userId">用户编号</param>


                
/// <returns></returns>


                
public void DeleteByID()


                 {


                        
int userId = instance.GetMaxUserId();


                         instance.Delete(userId);


                 }


    


                 [Test]


                
/// <summary>


                
/// 删除用户


                
/// </summary>


                
/// <param name="userId">用户实体</param>


                
/// <returns></returns>


                
public void Delete()


                 {


                        
int userId = instance.GetMaxUserId();


                         UserInfo info = instance.Read(userId);


                        
//Console.WriteLine("MaxUserId=" + userId);


                         instance.Delete(info);


                 }


         }


}

 上面的代码在NUnit2.5.3中测试通过。

 四、总结
 NHibernate与ADO.NET相比开发更简单,应对数据库的变化更灵活,而Linq to SQL比NHibernate更方便应对数据库变化,开发效率也高,使用Linq to SQL后我们仅需要编写一个类就足够了,比较遗憾的是Linq to SQL只支持SQL Server,所以很多人都在使用Entity Framework这个ORM框架了。

 周公

 2010-04-05
本文出自 “周公(周金桥)的专栏” 博客,请务必保留此出处http://zhoufoxcn.blog.51cto.com/792419/293966
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: