【转载】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>();
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的设计文件中的定义如下:
可以看出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(), );
}
[Test]
/// <summary>
/// 创建用户
/// </summary>
/// <param name="info">用户实体</param>
/// <returns></returns>
public void Create()
{
UserInfo info = new UserInfo()
{
Age = ,
Email = "zzz@ccav.com",
Mobile = "",
Phone = "",
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();
Assert.NotNull(info);
}
[Test]
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="info">用户实体</param>
/// <returns></returns>
public void Update()
{
UserInfo info = instance.Read();
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框架了。下一篇就要讲述ADO.NET Entity Framework的用法了。

【转载】ADO.NET与ORM的比较(3):Linq to SQL实现CRUD的更多相关文章

  1. 【转载】ADO.NET与ORM的比较(4):EntityFramework实现CRUD

    [转载]ADO.NET与ORM的比较(4):EntityFramework实现CRUD 说明:个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hiber ...

  2. 【转载】ADO.NET与ORM的比较(2):NHibernate实现CRUD

    [转载]ADO.NET与ORM的比较(2):NHibernate实现CRUD  转自周公 说明:个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hibe ...

  3. LINQ to SQL和Entity Framework对比与关联 (转载)

    LINQ to SQL和Entity Framework对比与关联       LINQ to SQL和Entity Framework都是一种包含LINQ功能的对象关系映射技术.他们之间的本质区别在 ...

  4. 转载一篇文章:LINQ TO SQL 大全

    https://www.cnblogs.com/chenwolong/p/lts.html 最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河 ...

  5. LINQ to SQL语句(19)之ADO.NET与LINQ to SQL

    它基于由 ADO.NET 提供程序模型提供的服务.因此,我们可以将 LINQ to SQL 代码与现有的 ADO.Net 应用程序混合在一起,将当前 ADO.NET 解决方案迁移到 LINQ to S ...

  6. 转载linq to sql 的详解

    [转]LINQ To SQL 语法及实例大全 2011-11-26阅读38651 评论9 LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL ...

  7. linq to sql转载

    LINQ简介 LINQ:语言集成查询(Language INtegrated Query)是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库 ...

  8. 查询大数据表的效率对比:Linq to SQL、Entity Framework、企业库存储过程、ADO.Net

    最近因为要开发大数据量网站,特作比较. Linq to SQL 查询 记录数:399997Linq to SQL 查询 Milliseconds:1910视图查询 记录数:399997视图查询 Mil ...

  9. LINQ体验(13)——LINQ to SQL语句之运算符转换和ADO.NET与LINQ to SQL

    运算符转换 1.AsEnumerable:将类型转换为泛型 IEnumerable 使用 AsEnumerable<TSource> 可返回类型化为泛型 IEnumerable 的參数.在 ...

随机推荐

  1. Android应用中使用Popupmenu

    最终效果: 页面布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns: ...

  2. 为什么要用Math.sqrt(i)方法

    java 练习题 判断 101-200 之间有多少个素数,并输出所有素数 public class Prime { public static int count = 0; public static ...

  3. js工厂模式

    设计工厂模式是为了创建对象.通常在类或者类的静态方法中实现,具有两个目标.其中一个是:当创建相似对象时执行重复操作: 另外一个目标是:编译时不知道具体类型(类)的情况下,为工厂客户提供一种创建对象的接 ...

  4. 网页中flash背景透明

    <embed src="文件路径" width="长度" height="宽度" quality="high" t ...

  5. 丰富的else语句及简洁的with语句 - 零基础入门学习Python034

    丰富的else语句及简洁的with语句 让编程改变世界 Change the world by program 丰富的else语句 有鱼油可能会说,else语句还有啥好讲的?经常跟if语句进行搭配用于 ...

  6. js判断输入的是单字节还是双字节

    计算机上每一个字符.数字.汉字.字母等,都对应着unicode编码,unicode编码小于255的为单字节,大于255.小于65535的为双子节或三字节 查看一个字符对应的unicode编码 var ...

  7. 火狐的打开3D效果

    最近研究网页的时候,想看看一个页面中盒子的层次问题,点击右键查看元素的后,没有发现3D效果的按钮. 在网上百度后说要什么显卡支持,以为是公司的电脑用的是集显,就没有这个功能.回去用自己的笔记本后,发现 ...

  8. ORA-16014报错解决

    今天在本地数据库操作的时候报错: SQL> alter database open;alter database open*第 1 行出现错误:ORA-16014: 日志 3 的序列号 55 未 ...

  9. java.lang.OutOfMemoryError: unable to create new native thread(转)

    解决 - java.lang.OutOfMemoryError: unable to create new native thread 工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文 ...

  10. windows phone中三种解析XML的方法

    需求如下, 项目需要将一段xml字符串中的信息提取出来 <?xml version=""1.0"" encoding=""UTF-8& ...