手把手教你用好LINQ to SQL(1)

From: http://developer.51cto.com/art/200904/120915.htm

作者写下这篇文章的主要目的不是“一口吃成个胖子”让大家一次就学会LINQ to SQL。而是从不同的方面帮助大家正确理解,所以这里提到的快速的含义是提高效率,而不是单纯为了学习的速度。


最近接连遇到几个朋友问我同一个问题,就是关于.NET平台上ORM框架的选择。我想在这个讲求 效率的时代,谁也不想手写SQL或存储过程去访问数据库了。大家都知道,在Java平台上,ORM 这一块基本是Hibernate的天下。当然,相对轻量级的iBatis也有不错的表现。

不过谈到.NET平台,ORM框架似乎相对混乱了点。很多朋友问我的时候,往往会这样问: NHibernate、NBear和Castle该选择哪个?而当我反问:为什么不适用微软自带的Linq to SQL 呢?对方经常会迷茫和不解。

我觉得这是个很奇怪的现象。依照我个人的实践,我认为当需要快速构建一个中小型项目时 ,Linq to SQL是一个很好的选择。你至少有以下理由可以选择它:

i. 它是微软自己的产品,和.NET平台有着天生的适应性。如果你使用.NET Framework3.5和 VS2008开发环境,它本身就集成在里面了,同时VS2008对于Linq to SQL给予了诸多方便的支持 。使用它,你不仅在开发和部署时不用考虑第三方库,更可以尽情享受VS2008带来的种种方便 。

ii. 上手十分容易,使用十分轻松,通常,你不需要编写一行代码,也不用写任何XML配置 ,完全通过可视化拖拽就能完成ORM层的构建。

iii. 功能丰富,使用便捷。当轻松构建好ORM层后,你就可以更轻松的操纵数据库了。Linq to SQL提供了丰富的功能,完全可以满足日常数据访问的需求。使用方法也非常简单、灵活。

有这么好的理由,我真想不通为什么那么多人不愿去选择它。我想来想去,也许有两个重要 原因,一是把LINQ和Linq to SQL混为一谈了,二是受前段时间“LINQ已死”的误导,觉得微软 已经抛弃Linq to SQL了。关于这两点,我就不细说了,简略澄清一下:

首先,LINQ是从.NET Framework3.0开始,.NET平台上引入的一种新式语言特性,狭义一点 ,你可以讲它理解成一种新式语法,主要是针对迭代数据操作的,所以,也许LINQ叫做“数据 迭代引擎(Data Iterative Engine)”更合适,之所以不着样命名,我想微软可能不愿意让自 己产品的简写为“DIE”吧。:-)而Linq to SQL是LINQ在数据库访问方面的一个应用框架,完全 是两码事。

其次,关于微软会不会放弃Linq to SQL,客观说,可能会,因为微软下一步主推的ORM解决 方案是Entity Framework。不过这并不妨碍你学习使用Linq to SQL,原因如下:第一,考虑到 兼容性问题,微软绝对不会把Linq to SQL从.NET Framework中拿掉的,所以你不用怕现在用 Linq to SQL写的程序以后不能运行了。第二,即使微软不更新Linq to SQL了,但它现在的功 能,已经足够满足我们日常需要了,相比重量级的Entity Framework,如果你只是做一个中小 型项目,并且很注重开发效率和学习曲线,为什么不选择可爱的Linq to SQL呢?

好的,上面废话说了不少,下面正式开始吧。本文不是一篇关于Linq to SQL的大百科,写 本文的目的,是引导大家快速上手Linq to SQL,所以不可能面面俱到去讲解Linq to SQL。不 过根据80-20定律,学会了本文的内容,基本就可以应付80%的工作了。另外,延续我一贯的风 格,本文将通过案例的方式帮大家上手Linq to SQL。案例是一个“公告发布程序”。下面我们 开始!

Step1:建立数据库

在使用Linq to SQL前,我们要将相应的数据库建好。在这个Demo中,使用的数据 库是SQL Server Express 2005。

我们首先建立一个叫的数据库MyBulletin,及两个数据表:Category和Bulletin,分别表示 公告的分类和公告,建立方法不再赘述。至于两个表的具体字段请参看图1。

01

图1、数据表结构

其中Category和Bulletin存在一个一对多的关联,表示一个分类下可以有多条公告。

Step2:建立Linq to SQL Classes文件

数据建好后,我们需要建立Linq to SQL Classes文件。这种文件是Linq to SQL框架的主要 文件,后面自动生成的实体类和ORM代码都存在于这个文件中。

我们打开VS2008,新建一个C# Class Labrary工程,名称为LinqToSqlDemo.Orm,建好后在 工程上单击右键,选择“Add”->“New Item”,在文件类型中选择“Linq to SQL Classes ”,文件名命名为“DataClasses.dbml”,如图2所示。

02

图2、新建Linq to SQL Classes文件


Step3:根据数据库表自动生成代码

当建好Linq to SQL Classes后,VS主界面中自动打开了这个文件。可以看到,这 个文件实际是一个设计文件,目前还不包含任何代码和元素。下一步就是利用我们刚才的数据 库自动生成ORM代码了。

打开Server Explorer面板。一般它位于VS的左上角,如果没有,请到View菜单中去打开。 然后在Date Connections上右键单击,选择“Add Connection”,从这里添加对数据库 MyBulletin的连接。

03

图3、添加数据库连接

如图3所示,在Server name中填入SQL Server数据库服务的名字,如果使用的是SQL Server Express 2005,服务名一般是“计算机名\SQLEXPRESS”的格式,然后在“Select or enter a database name”中选择MyBulletin,单击“OK”,就连上我们所需的数据库了。

这时,展开这个连接下的Tables节点,应该能看到Category和Bulletin两个表,选中两个表 ,将它们拖到DataClasses.dbml的设计区,就会看到如图4所示的样子。

04

图4、设计视图

然后,按Ctrl+S保存,OK!ORM构建完了!

没有骗你,所有需要的代码已经生成完成,现在可以使用它们操作MyBulletin数据库了。不 要怀疑,Linq to SQL使用起来就是这么轻松加愉快,不需要写一行代码,也不需要写一个XML 字符,ORM就构建完了!

我知道你没看到生成的东西可能不太放心,那么你可以在Solution Explorer里展开 DataClasses.dbml节点,看到里面的DataClasses.designer.cs文件没,打开它,里面就是刚才 自动生成的代码,我们的数据访问操作就靠这些代码了。另外顺表提一下,数据库的连接字符 串放在工程根目录下的app.config文件里,这也是自动生成的,打开它,就可以看到连接字符 串。以后如果要修改连接字符串,就修改这里。

好了,ORM构建好了,下面我们看看怎么用。

Step4:使用Linq to SQL访问数据库

我们首先新建一个工程。为了简单起见,我们就直接建立一个C# Console Application测试 我们的ORM吧。将这个工程命名为LinqToSqlDemo.Test。当然,建好工程后,不要忘了添加对工 程LinqToSqlDemo.Orm的引用,还要添加对“System.Data.Linq”命名空间的引用。

然后,我们打开Program.cs文件,将其中的内容替换为如下测试代码。

using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;
using System.Text;using LinqToSqlDemo.Orm;namespace LinqToSqlDemo.Test
{class Program{private static DataClassesDataContext dataContext = new DataClassesDataContext();private static void Output(){//输出分类信息foreach (Category c in dataContext.Categories){Console.WriteLine("分类" + c.ID + ":" + c.Name);}//输出体育新闻下的公告信息Category categorySport = dataContext.Categories.Single(c => c.Name == "体育新闻");foreach (Bulletin b in categorySport.Bulletins){Console.WriteLine("标题:" + b.Title);Console.WriteLine("内容:" + b.Content);Console.WriteLine("发布日期:" + b.Date);Console.WriteLine("所属分类:" + b.Category1.Name);}}private static void TestInsert(){//生成分类实体类Category category1 = new Category(){Name = "国际要闻"};Category category2 = new Category(){Name = "体育新闻"};Category category3 = new Category(){Name = "财经快报"};//生成公告实体类Bulletin bulletin1 = new Bulletin(){Content = "曼联晋级冠军杯四强",Date = DateTime.Now,Title = "曼联晋级冠军杯四强"};Bulletin bulletin2 = new Bulletin(){Content = "18:00直播亚冠首尔VS山东,敬请期待!!!",Date = DateTime.Now,Title = "18:00直播亚冠首尔VS山东"};//将公告加入相应分类category2.Bulletins.Add(bulletin1);category2.Bulletins.Add(bulletin2);//加入数据库dataContext.Categories.InsertOnSubmit(category1);dataContext.Categories.InsertOnSubmit(category2);dataContext.Categories.InsertOnSubmit(category3);dataContext.SubmitChanges();}private static void TestDelete(){dataContext.Categories.DeleteOnSubmit(dataContext.Categories.Single(c => c.Name == "国际要闻"));dataContext.SubmitChanges();}private static void TestUpdate(){Category categoryFinance = dataContext.Categories.Single(c => c.Name == "财经快报");categoryFinance.Name = "财经新闻";dataContext.SubmitChanges();}static void Main(string[] args){Console.WriteLine("==============================Linq to SQL 测试==============================");Console.WriteLine();Console.WriteLine("==============================测试Insert==============================");Console.WriteLine();TestInsert();Output();Console.WriteLine("==============================测试Delete==============================");Console.WriteLine();TestDelete();Output();Console.WriteLine("==============================测试Update==============================");Console.WriteLine();TestUpdate();Output();Console.ReadLine();}}
}


一下子看不懂上述代码页没有关系,稍候我们会解释一下。现在,我们先来看运行结果:

06

图5、测试程序运行结果

我们先来看看这段测试程序做了什么事。刚开始,数据库是空的,我们首先插入三个分类, 并在“体育新闻”下插入两条公告,这是对Insert的测试。接着,我们删除了“国际要闻”分 类,这是对Delete的测试。然后,我们将“财经快报”改为“财经新闻”,这是对Update测试 。另外,整个过程的输出当然是对Select的测试。这样,数据库基本的操作都测试过了。从输 出结果来看,我们的ORM组件运行很顺利,程序输出正确。

程序分析

经过简单的四步,我们就完成了通过Linq to SQL操作数据库的过程。下面我们对 测试代码进行一个简要的分析,帮助朋友们学会Linq to SQL操作数据库的基本方法。

取得数据库Gateway

要操作数据库,我们首先要获得一个DataContext对象,这个对象相当于一个数据 库的Gateway,所有的操作都是通过它进行的。这个对象的名字是“Linq to SQL Classes文件 名+‘DataContext’”,这里,就是DataClassesDataContext了。它和普通对象一样,直接实 例化就行了。在Demo里我将它实例化为一个静态变量。

取得DataContext对象后,每个数据表就会映射到其一个集合属性,例如Category表映射到 dataContext.Categories,这是一个集合属性,每一个元素是一个实体类,代表此表中的一条 记录。实体类名和表名相同。实体类的字段自然就映射到对应表的字段。

还有一点需要注意,数据库中的一对多关系,在Linq to SQL生成代码时会自动表示到类结 构中。并且,这种关联是双向的。例如,Category与Bulletin的一对多关系,到了类结构中, 反映成如下形式:在Category类中,有一个名为Bulletins的集合属性,内容是所有属于此 Category的Bulletin对象的引用。而在Bulletin类中,也会有个Category1属性(由于Category 这个名字被我们用了,所以,这个关联属性自动加了个“1”),其内容是此Bulletin所属 Category对象的引用。

Insert操作

Insert用于向数据库添加记录。一般情况下,使用“DataContext.表映射集 合.InsertOnSubmit(实体类)”的方式就可以完成Insert操作。不过这里要注意一点,由于Linq to SQL使用了“Unit of Work”模式,所以,对数据库的操作不会立即提交到数据库,而要调 用DataContext的SubmitChanges方法,所有改动才会被提交到数据库。

Delete操作

Delete操作用于从数据库中删除记录。表映射集合的DeleteOnSubmit方法可以实 现这个操作。这个方法需要一个参数,就是要删除的实体类,这里不能直接传个ID去删除,要 首先通过ID找到相应实体类,传给DeleteOnSubmit再删除。当然最后不要忘了SubmitChanges。

Update操作

Update操作用于更新数据库中某已存在记录的信息。在Linq to SQL中,Update操 作就是首先加载相应的实体类,修改其相应字段后,SubmitChanges就可以了。

Select操作

Select操作用于从数据库中返回指定的记录。在Linq to SQL中,查询结果都是以实体类或 实体类集合的方式返回的。其中实体类集合并不是List,如果想转为List,只需在返回结果上 调用ToList方法即可。

如果是查询单一记录,建议使用表映射集合的Single方法。至于查询参数,建议采用lambda 表达式。如果你对lambda表达式不熟,可以参考这里http://msdn.microsoft.com/zh- cn/library/bb397687.aspx

其它相关示例代码

常用Select操作举例

取得单个记录(ID为3的分类)

RETURNDATACONTEXT.CATEGORIES.SINGLE(C=>C.ID==3;

取得全部记录(全部分类)

RETURNDATACONTEXT.CATEGORIES;

得部分记录(所属分类ID为3的公告,按ID降序排列)

RETURNFROMBorderbyb.IDdescending 

selectb;

取得部分记录并分页,最后转换为List(所属分类ID为3的公告并分页,pageSize为每页多 少条记录,pageNo为第几页)

varbulletins=frombINDATACONTEXT.BULLETINS

orderbyb.IDdescending

selectb;

总结

好了,这篇文章就到这里了。希望能帮助大家快速上手Linq to SQL。关于Linq to SQL,还 有许多丰富的功能和细节问题,篇幅原因不能详述,各位可以参考相关资料。

编者附注

网友wiken chan在跟着程序写了一遍后,发现文中代码部分,表名部分均由出错,与本文介绍中建立的表名有出入,并进行了更正测试。在此向网友wiken chan表示感谢。

using System;  
using System.Collections.Generic;  
using System.Data.Linq;  
using System.Linq;  
using System.Text;  
using LinqToSqlDemo.Orm;  
namespace LinqToSqlDemo.Test  
{  class Program  {  private static DataClassesDataContext dataContext = new DataClassesDataContext();  private static void Output()  {  //输出分类信息  foreach (Category c in dataContext.Category)  {  Console.WriteLine("分类" + c.ID + ":" + c.Name);  }  //输出体育新闻下的公告信息  Category categorySport = dataContext.Category.Single(c => c.Name == "体育新闻");  foreach (Bulletin b in categorySport.Bulletin)  {  Console.WriteLine("标题:" + b.Title);  Console.WriteLine("内容:" + b.Content);  Console.WriteLine("发布日期:" + b.Date);  Console.WriteLine("所属分类:" + b.Category1.Name);  }  }  private static void TestInsert()  {  //生成分类实体类  Category category1 = new Category()  {  Name = "国际要闻" };  Category category2 = new Category()  {  Name = "体育新闻" };  Category category3 = new Category()  {  Name = "财经快报" };  //生成公告实体类  Bulletin bulletin1 = new Bulletin()  {  Content = "曼联晋级冠军杯四强",  Date = DateTime.Now,  Title = "曼联晋级冠军杯四强" };  Bulletin bulletin2 = new Bulletin()  {  Content = "18:00直播亚冠首尔VS山东,敬请期待!!!",  Date = DateTime.Now,  Title = "18:00直播亚冠首尔VS山东" };  //将公告加入相应分类  category2.Bulletin.Add(bulletin1);  category2. Bulletin.Add(bulletin2);  //加入数据库  dataContext.Category.InsertOnSubmit(category1);  dataContext. Category.InsertOnSubmit(category2);  dataContext. Category.InsertOnSubmit(category3);  dataContext.SubmitChanges();  }  private static void TestDelete()  {  dataContext.Category.DeleteOnSubmit(dataContext.Category.Single(c => c.Name == "国际要闻"));  dataContext.SubmitChanges();  }  private static void TestUpdate()  {  Category categoryFinance = dataContext.Category.Single(c => c.Name == "财经快报");  categoryFinance.Name = "财经新闻";  dataContext.SubmitChanges();  }  static void Main(string[] args)  {  Console.WriteLine("==============================Linq to SQL 测试==============================");  Console.WriteLine();  Console.WriteLine("==============================测试Insert==============================");  Console.WriteLine();  TestInsert();  Output();  Console.WriteLine("==============================测试Delete==============================");  Console.WriteLine();  TestDelete();  Output();  Console.WriteLine("==============================测试Update==============================");  Console.WriteLine();  TestUpdate();  Output();  Console.ReadLine();  }  }  
} 



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/406380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

长期对着电脑是对身体很哟影响的

笔记本电脑由于其轻,灵活性和新设施像WiFi,允许人们使用互联网几乎无处不在,已经成为许多人的一个组成部分的生活尤其是年轻人。每个人都同意,有一台笔记本电脑是没有害处的 。但问题是,人们紧张他们的眼睛在非常不健康,长时间不合适的姿势。年轻人使用大部分的休闲时间在他们的…

Taro+react开发(69):传入localstoage需要jsonstringfy处理

this.setState({answerList: [...answerList, ...[val]],...val},() > {localStorage.setItem("answerList", JSON.stringify(answerList));});

一个关于人工智能实现的讨论

突然发现一场战争刚刚过去,自己没有来得及参战,战利品当然就没有机会了,不过观战也是不错的选择。这篇帖子讨论的非常不错,大家都阐述了自己的观点,值得一看 前面写过一些文章来讨论人工智能,我的观点就是以…

vue移动端的一款音频插件vue-aplayer

vue移动端的一款音频插件vue-aplayer

VC中为对话框添加背景图片

From: http://blog.ezcn8.com/2011/06/11/vc%E4%B8%AD%E4%B8%BA%E5%AF%B9%E8%AF%9D%E6%A1%86%E6%B7%BB%E5%8A%A0%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87/ VC中为对话框添加背景图片也很简单,可以有以下两种方法: 1. 使用画刷CBrush void CDlg::OnPaint()…

再好的工作是为了更好的生活

2015-02-08 00:11 不过没有的好的工作是不容易好好生活的。 //z 2015-02-08 00:11:35 L.32685705 BG57IV3BYH T1976877610.K.F2506529148[T1,L106,R4,V35] 感动就像糖醋排骨里的糖,光有白糖虽然很甜,可是甜得没有根据,多吃几口就腻歪了&#…

隐藏自己电脑的IP地址

你的电脑总会受到别人***吗?隐藏自己电脑的IP地址,可以让别人难以***。这里就为大家介绍一种隐藏IP的方法: 第一步:用本地安全策略,先打开IP安全策略,方法是在“运行”里输入 secpol.msc或着在控制面板里打…

esxi管理端口_网工知识角|一分钟轻松了解华为端口安全机制

学网络,就在IE-LAB国内高端网络工程师培养基地为防止MAC地址洪泛攻击,防止未经允许的设备访问网络,并增强安全性。通过端口安全机制,录连接到交换机端口的以太网MAC地址,只允许某个或者某些合法设备通过相应的端口进行…

VC设置CEdit控件背景透明、文字背景也透明

开发环境:VC6, a dialog based MFC application. 主界面: 为对话框添加WM_CTLCOLOR消息响应函数: HBRUSH CDDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {HBRUSH hbr CDialog::OnCtlColor(pDC, pWnd, nCtlColor);…

[leetcode]Generate Parentheses

题目: Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. For example, given n 3, a solution set is: "((()))", "(()())", "(())()", "()(())", "()()(…

小议程序员编写技术文档

一提到写文档,可能很多程序员可能会不屑一顾,但是,无论处于规范开发流程,还是就于逃避嫌责的目的,能够将自己所从事的工作用文档描述记录下来,还是一件很有成就感的事情,抛开其功用不谈&#xf…

Taro+react开发(71):Taro.nextTick

Taro.nextTick(callback) 延迟一部分操作到下一个时间片再执行。(类似于 setTimeout) 说明 因为自定义组件中的 setData 和 triggerEvent 等接口本身是同步的操作,当这几个接口被连续调用时,都是在一个同步流程中执行完的&#xf…

led拼接屏报价_LED拼接屏的装饰

LED拼接屏外装饰工程是利用结构连接件或者粘结剂将装饰材料固定到钢结构框架的外部,使之达到一个美观大方的外形,并且达到防水(针对户外)等防护目的。LED屏的常用装饰的材料如下。(1)不锈钢一般装饰使用的不锈钢主要有亚光拉丝不锈钢、镜面不锈钢&#x…

58-混沌感悟.(2015.2.11)

混沌感悟混沌出现孕育秩序,稳态必将走向自我毁灭。稳态只会在系统内运动,混沌打破稳态,才会形成超越原系统的新秩序。市场所欲,即我所欲通常,能量遵循最小阻力途径。最小阻力需根据形而上、形而下来结合。习惯思维是&a…

Taro+react开发(72):Taro.createSelectorQuery

Taro.createSelectorQuery() 返回一个 SelectorQuery 对象实例。可以在这个实例上使用 select 等方法选择节点,并使用 boundingClientRect 等方法选择需要查询的信息。

对话框找不到WM_ERASEBKGND消息的解决方法与对话框背景图片的载入方法

From: http://wmnmtm.blog.163.com/blog/static/38245714201041535119716/ 为了让对话框程序更为漂亮,一般都是在窗口的WM_ERASEBKGND消息处理函数OnEraseBkgnd中添加如下代码. BOOL CMFCtestDlg::OnEraseBkgnd(CDC* pDC) {// TODO: Add your message handler code here and…

Symantec改变了产品下载方式

随着Windows7的部署,开始启用Symantec Endpoint替代之前的Symantec Antivirus以及Symantec Client Security。今日本打算去Symantec网站去下载SEP的安装光盘,才发现Symantec改变了产品的下载方式。晕,看来要等一等了。Starting on February 1…

电感检测_三、电感线圈的识别与检测(二)

变压器变压器也是一种电感器。它是利用两个 电感线圈靠近时的互感现象工作的,是电子产品中十分常见的元件。变压器是将两组或两组以上线圈绕在同一骨架上,并在绕好的线圈中插入铁芯或磁芯等导磁材料而构成,它在电路中起电压变换和阻抗变换等作…