zoukankan      html  css  js  c++  java
  • 【转载】ADO.NET与ORM的比较(3):Linq to SQL实现CRUD

    【转载】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的类,如下图所示:
     linq
     在名称一栏中填写较友好的名字之后,然后项目中就会增加一个后缀为dbml的文件,双击这个文件就会进入设计视图,如下图所示:
     5
     在服务器资源管理中找到相应的数据库连接,依次点开之后就可以将数据库中的表拖到dbml设计器上。如果读者界面上没有服务器资源管理器可以使用CTRL+ALT+S组合键将其调出来。如果没有数据库连接,可以按照下面的步骤进行,在服务器资源管理器中的“数据连接”——“添加连接”,出现如下界面:
     
     
     在上面的界面中依次填写好数据库、用户名和密码及要连接的库名之后,点击确定,这样在服务器资源管理器中就增加了一个数据库连接,展开之后如下图所示:
     
     拖拽一个表到dbml上就会自动生成这个表的实体类,如下图所示:
     2
     也许有人会思考这个类的定义在哪里,可以告诉你的是这个类的定义在这个dbml文件对应的cs文件中(dbml文件名.designer.cs这种形式),如下图所示:
    1 
     有些这些之后我们就可以动手编码实现对数据库进行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;  
            }  
        }  
    }  
    View Code

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

    [System.Data.Linq.Mapping.DatabaseAttribute(Name="AspNetStudy")]  
    public partial class UserInfoDataClassesDataContext : System.Data.Linq.DataContext  
    {  
    //.....省略其它代码  
    }  

    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);  
            }  
        }  
    }  
    View Code

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

  • 相关阅读:
    数据结构-树与二叉树-思维导图
    The last packet successfully received from the server was 2,272 milliseconds ago. The last packet sent successfully to the server was 2,258 milliseconds ago.
    idea连接mysql报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property
    redis学习笔记
    AJAX校验注册用户名是否存在
    AJAX学习笔记
    JSON学习笔记
    JQuery基础知识学习笔记
    Filter、Listener学习笔记
    三层架构学习笔记
  • 原文地址:https://www.cnblogs.com/witeem/p/4156639.html
Copyright © 2011-2022 走看看