Linq学习随笔三------LINQ to SQL

LINQ to SQL provides a run-time infrastructure for managing relational data as objects. In LINQ to SQL, the data model of a relational database is mapped to an object model expressed in the programming language of the developer. When you execute the application, LINQ to SQL translates language-integrated queries in the object model into SQL and sends them to the database for execution. When the database returns the results, LINQ to SQL translates them back into objects that you can manipulate.

LINQ to SQL includes support for stored procedures and user-defined functions in the database, and for inheritance in the object model.

从上面的描述我们可以看出来LINQ to SQL实际上是ORM结构的,LINQ to SQL 会将对象模型中的语言集成查询转换为 SQL,然后将其发送到数据库进行执行。 数据库返回结果时,LINQ to SQL 会将结果转换回可操作对象。在展开下面的话题之前,大家需要做点准备工作,先创建一个DB,添加一个表,DB设计成什么样对下面的讲解的内容影响不大,闲话不多说,接下来直接上干货儿。

1.创建Object Model

Object Model是根据数据库结构创建的,每个表对应一个类,DB对应一个类,该类继承System.Data.Linq.DataContext,如果自己手动编写,规模比较小的DB的工作量还好说,如果表多的话,那手动编写这部分代码就太累了,根据微软官方的介绍,有两种tools可以根据DB生产Object Model,Object Relational Designer和SQLMetal,Object Relational Designer是VS中自带的IDE,本文里只对Object Relational Designer的时候进行介绍。

a.右键工程,add new item,选择LINQ to SQL Classes

b.在Server Explorer中右键Data Connections,Add Connection,添加之前准备的DB,之后将DB中的表拖拽到.dbml界面中2的部分,如果DB中有存储过程,拖拽到.dbml界面界面中3的部分

完成以上操作后会在.dbml下的cs文件中自动生产Object Model code

2.如何调用自动生产的Object Model code

 1        using (HerosOMDataContext ctx = new HerosOMDataContext("server=XXXXX;database=XXXX;uid=XX;pwd=XXXXX"))
 2             {
 3                 var hh = from h in ctx.Heros
 4                          where h.StateId == 2
 5                          select h;
 6                 List<Hero> hList = hh.ToList<Hero>();
 7                 int maxId = (from h in ctx.Heros
 8                              orderby h.Id
 9                              select h.Id).Max();
10                 int wuStateId = (from s in ctx.States
11                                  where s.Name == "Wu"
12                                  select s.Id).SingleOrDefault();
13                 int shuStateId = (from s in ctx.States
14                                   where s.Name == "Shu"
15                                   select s.Id).SingleOrDefault();
16                 int weiStateId = (from s in ctx.States
17                                   where s.Name == "Wei"
18                                   select s.Id).SingleOrDefault();
19                 ctx.Heros.InsertOnSubmit(new Hero { Id = maxId + 1, Name = "GanNing", Weapon = "Dao", StateId = wuStateId });
20                 ctx.SubmitChanges();
21                 ctx.Heros.DeleteAllOnSubmit(from h in ctx.Heros
22                                             where h.Name == "ZhouYu"
23                                             select h);
24                 ctx.SubmitChanges();
25                 Hero hero = ctx.Heros.Where(h => h.Name == "XiaHouDun").FirstOrDefault();
26                 hero.Weapon = "DaDao";
27                 ctx.SubmitChanges();
28
29                 ctx.PROC_DeleteState(wuStateId, "Wu");
30                 ctx.ExecuteCommand("insert into State (Id,Name,Master) values ({0}, {1}, {2})", 1, "Wu", "SunQuan");
31             }

第一行代码既是继承System.Data.Linq.DataContext的类,我们通过构造HerosOMDataContext类,来指定连接哪个DB,2-13行的代码和之前文章中讲到的Linq的用法并没有什么不同,唯一的区别就是操作的数据集合不同而已,既然是针对SQL,所以对于SQL有的增,删,改,查是少不了的。

a.增

上面示例代码中的14-15行对应的就是添加操作,从调用方式看,和我们平时往集合中插入操作没什么区别,唯一的区别就是调用InsertOnSubmit(TEntity entity)后,添加的object不会立刻加入到数据库里,只有接着调用方法SubmitChanges()后,才会真正的在DB中执行“增”操作,如果对于SQL server中执行的是什么样的语句比较好奇,可以使用SQL Server Profiler监控下。

b.删

上面示例代码中的16-19行对应的就是删除操作,从使用方法上没有什么需要特别注意的,依然是在调用方法SubmitChanges()后,才会真正的在DB中执行“删”操作。

c.改

上面示例代码中的20-22行对应的就是修改操作,先获取需要修改的对象,之后更新需要修改的属性,最后依然是在调用方法SubmitChanges()后,才会真正的在DB中执行“改”操作。

d.查

上面示例代码中的2-13行对应的就是修改操作,这一部分的使用方法和之前文章介绍的Linq的使用没有什么区别,和Linq to object和Linq to xml时一样,查询是异步的,只有真正调用时才会执行。

e.执行存储过程

上面示例代码中的24行对应的就是执行DB中的存储过程,在Object Relational Designer中拖拽DB中里的存储过程后,会在DataContext类中自动生产一个与存储过程同名的方法,方法的参数与存储过程中定义的参数相同,在执行存储过程时不需要调用方法SubmitChanges(),在调用存储过程同名的对应方法时,会立即在DB中执行该存储过程。

f.直接执行SQL语句

上面示例代码中的25行中调用的方法ExecuteCommand(string command, params object[] parameters),给用户提供了直接执行SQL语句的接口,另外方法ExecuteQuery也是类似的功能。

g.Attach

Use the Attach methods with entities that have been created in one DataContext, serialized to a client, and then deserialized back (with the intention to perform an update or delete operation). For more information, see Data Retrieval and CUD Operations in N-Tier Applications (LINQ to SQL).

Do not try to Attach an entity that has not been detached through serialization. Entities that have not been serialized still maintain associations with deferred loaders that can cause unexpected results if the entity becomes tracked by a second data context.

When a new entity is attached, deferred loaders for any child collections (for example, EntitySet collections of entities from associated tables) are initialized. When SubmitChanges is called, members of the child collections are put into an Unmodified state. To update members of a child collection, you must explicitly call Attach and specify that entity.

可以这么去理解上面的介绍,通过两个DataContext分别获取的实体,起生命周期只限于自己的DataContext里,如果想把当前的DataContext里得到的实体用在另一个DataContext里,就需要通过attach给这个实体“续命”,让他在新的DataContext里继续“活着”,前面用生命周期来解释实际是不准确的,但是这样的说法可能理解起来更简单点,结合下面的示例文件能更容易理解点

 1 //通常,通过从其他层反序列化XML获取要附加的实体
 2 //此示例使用 LoadWith 在一个查询中预先加载客户和订单,
 3 //并禁用延迟加载
 4 Customer cust = null;
 5 using (NorthwindDataContext tempdb = new NorthwindDataContext())
 6 {
 7     DataLoadOptions shape = new DataLoadOptions();
 8     shape.LoadWith<Customer>(c => c.Orders);
 9     //加载第一个客户实体及其订单
10     tempdb.LoadOptions = shape;
11     tempdb.DeferredLoadingEnabled = false;
12     cust = tempdb.Customers.First(x => x.CustomerID == "ALFKI");
13 }
14 Order orderA = cust.Orders.First();
15 Order orderB = cust.Orders.First(x => x.OrderID > orderA.OrderID);
16 using (NorthwindDataContext db2 = new NorthwindDataContext())
17 {
18     //将第一个实体附加到当前数据上下文,以跟踪更改
19     db2.Customers.Attach(cust);
20     //附加相关订单以进行跟踪; 否则将在提交时插入它们
21     db2.Orders.AttachAll(cust.Orders.ToList());
22     //更新客户的Phone.
23     cust.Phone = "2345 5436";
24     //更新第一个订单OrderA的ShipCity.
25     orderA.ShipCity = "Redmond";
26     //移除第二个订单OrderB.
27     cust.Orders.Remove(orderB);
28     //添加一个新的订单Order到客户Customer中.
29     Order orderC = new Order() { ShipCity = "New York" };
30     cust.Orders.Add(orderC);
31     //提交执行
32     db2.SubmitChanges();
33 }

h.冲突处理

因为是操作SQL数据库,所以不可避免的会有多线程的问题,随之而来的也就有冲突的问题产生,这部分不具体介绍,感兴趣的可以看下下面链接里面的内容

https://msdn.microsoft.com/en-us/library/bb399389(v=vs.90).aspx

未完待续......

时间: 2024-11-03 21:41:13

Linq学习随笔三------LINQ to SQL的相关文章

Linq学习随笔一------LINQ to Objects

Linq是Language Integrated Query的简称,它是C# 3.0中新添加的,包含在微软.net framework 3.5,用以简化查询查询操作.它主要包含了3块,Linq to Object.Linq to SQL.Linq to XML,其中Linq to Object和对于对象的查询,Linq to XML则又提供了对XML格式数据的检索.设置等功能,Linq to SQL顾名思义就是针对SQL的功能. 一.LINQ to Objects The term "LINQ

Linq学习随笔二------LINQ to XML

LINQ to XML LINQ to XML provides an in-memory XML programming interface that leverages the .NET Language-Integrated Query (LINQ) Framework. LINQ to XML uses the latest .NET Framework language capabilities and is comparable to an updated, redesigned D

MyBatis学习 之 三、动态SQL语句

有些时候,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息.使用Oracle的序列.mysql的函数生成Id.这时我们可以使用动态sql. 下文均采用mysql语法和函数(例如字符串链接函数CONCAT). 3.1 selectKey 标签 在insert语句中,在Oracle经常使用序列.在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键.使用myBatis的s

Linq学习之旅——LINQ查询表达式

1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. 概述 LINQ的全称是Language Integrated Query,中文译成“语言集成查询”.LINQ作为一种查询技术,首先要解决数据源的封装,大致使用了三大组件来实现这个封装,分别是LINQ to Object.LINQ to ADO.NET.LINQ to XML.它们和.NET语言的关系如下:

Linq学习(一)-初涉Linq

一.何谓LINQ LINQ:Language Integrated Query语言集成查询,其本质是对ADO.NET结果集通过反射连同泛型特性转换成对象集,实现OR模型的转换 二.优点与缺点 优点:封装了SQL语句,只对对象进行操作,代码量减少 缺点:追求效益的同时牺牲了性能,比起ADO.NET性能稍差,且对复制的sql语句也不好操作 三.支持那些查询 联合.分组.排序.连接查询 四.何谓Linq to sql Linq to sql是LINQ的一部分,全称基于关系型数据库的DotNet语言集成

Linq 学习之一 (Linq与DataTable)

将一个dataTABLE转化成linq: 1 DataTable dtChangeDetail = new DataTable(); 2 dtChangeDetail.Columns.Add("IsModi",typeof(Boolean)); //记录是否变动 3 dtChangeDetail.Columns.Add("FromDeptID", typeof(Int32)); 4 dtChangeDetail.Columns.Add("FromPostI

python学习随笔(三)_字符串

字符串***    是由一个个字符组成的有序的序列,是字符的集合    使用单引号,双向引号,三引号引住的字符序列    #三引号中可以放sql语句    字符串是不可变对象 字符串元素访问    字符串支持使用索引访问    有序列的字符集合,字符序列    字符串可以是个容器,可以被一个个迭代出来,因为它是有顺序的 字符串join连接*    "string".join(iterable) -> str        将可迭代对象连接起来,使用string作为分隔符     

linux学习随笔三

一.根目录详解 二.file命令使用 ls /  进入根目录 /boot 系统启动相关文件 如内核.initrd以及grub(bootloader)引导加载器 /dev 设备文件 浅蓝色链接文件,***为特殊文件 设备文件有: 块设备:随机访问,数据块 字符设备:线性访问,按字符为单位 设备号:主设备号(major)和次设备号(minor) /etc 配置文件 /home 用户家目录 每一个用户的家目录通常默认为/home/USERNAME形式存在 /root 管理员家目录(生产环境中不建议用r

Delphi面向对象学习随笔三:overload与override

作者:巴哈姆特(转载请注明出处并保持完整)    首先,我想单独说明一下overload,为什么呢?因为overload和对象化关联不大,所以,我感觉单独提出来说明比较好.    我们都知道,在Pascal语法规则中,同一个UNIT里是不能存在两个同名的函数的,例如: function func(): Boolean; function func(const x: Char): Boolean; 这样是会出语法错误的,原因是因为标识符规则限制.但是问题出来了,如果我们需要几个功能相似但是参数不同