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

简介:
说明:个人感觉在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框架了。












本文转自周金桥51CTO博客,原文链接:http://blog.51cto.com/zhoufoxcn/293966  ,如需转载请自行联系原作

相关文章
|
6天前
|
云安全 人工智能 安全
AI被攻击怎么办?
阿里云提供 AI 全栈安全能力,其中对网络攻击的主动识别、智能阻断与快速响应构成其核心防线,依托原生安全防护为客户筑牢免疫屏障。
|
16天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
10天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
621 216
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
860 61
|
8天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
1337 157
|
5天前
|
编解码 Linux 数据安全/隐私保护
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
249 138
|
7天前
|
存储 安全 固态存储
四款WIN PE工具,都可以实现U盘安装教程
Windows PE是基于NT内核的轻量系统,用于系统安装、分区管理及故障修复。本文推荐多款PE制作工具,支持U盘启动,兼容UEFI/Legacy模式,具备备份还原、驱动识别等功能,操作简便,适合新旧电脑维护使用。
551 109