SQL ServerLinqToDB 源码分析——前言

记笔者进入合作社的早晚接触的第一个ORM框架是Entity
Framework。为了Entity
Framework也扣了非把的英文材料(不是作者装B哦)。正式使用三个月后。笔者对客产生一个全面性的认识。我只好说他真正十分强大,也特别有利。可是我并无是怪喜爱他。要问为什么的语,笔者不得不说欣赏就是爱好。不爱就是未爱。不待了多之说辞。笔者就是这样子的一个人数。但是笔者非会见忽略他的强劲的一派。微软的靶子要老样子——开发简单化。只是以Entity
Framework的数量迁移上面笔者非是十分喜爱。至少在笔者团队开发过程不时会冒出因为本不对导至数据丢失。不管咋样笔者对Entity
Framework的运也至少发生同年的时日。由于路以世界让(DDD)为核心思想。所以在统筹之时段,会用到有些作者觉得还不易的盘算。比如工作单元(Unit
Of Work模式)。Entity
Framework于初期的时刻是匪开源码。笔者以前是由事JAVA开发的。这对笔者来讲心态及产生一些不可知接受(当然就吗是笔者个人心情)。终于Entity
Framework6始源码了。如果生趣味之爱侣可下载下来看看(源码地址:https://github.com/aspnet/EntityFramework6)。

其次年时笔者接触了亚只ORM框架是LinqToDB。笔者非是怀念强调LinqToDB有多好。笔者只是认为他是一个相当对的开源ORM框架。功能未比较EF差,用法达成十分接近的EF,却比EF来得轻量,而且同时大多发生了和睦之特征。所以要是您用EF用得有一点烦了或觉得EF有少数笨重。想去探访发生没有起别的ORM框架。不烦试试LinqToDB。

开条件


对此LinqToDB的dll包在NuGet上可以下载到。只要输入“linq2db”即可。同时也得于Github上面下载(https://github.com/linq2db/linq2db)。最好选以及笔者一样子的版本,比较稳定。如下

软件开发工具:Visual Studio 2013

LinqToDB版本:linq2db-Release.1.0.7.4

数据库:SQL Server 2008R

LinqToDB介绍


LinqToDB做呢一个轻量级的ORM框架。当然可以于开发人员用面向对象的思维来操作数据库。而且他依据是Linq上面进行开之。所以一般的Linq操作他吗是支持的。同时作者以壮大对应之DML和DDL。比如增加 Insert,
Delete, Update, CreateTable,
DropTable等方式。相对于EF来讲,LinqToDB显得还是颇死小,没有那强。LinqToDB可以说只有是管Linq动作成为对应之SQL语句。然后于展开操作数据库。这明显更加类似原生态之做法。也是作者为什么喜欢的触及有。那么LinqToDB到底能支撑小种数据库。作者在Github上吗举行吗明确指出来。如下。

SQL Server 1

LinqToDB是安利用也?作者在Github上面用了藏的Northwind数据库来教。不如笔者为来所以一下Northwind数据库进行教学本系列之片段试及列子。Northwind数据库是Sql
Server
2000数据库的藏设计之数据库。如果不晓得的朋友,请百度转。我们且掌握EF有三种植模式开发。那么是勿是象征LinqToDB也发生或产生立三栽出为?对于当下等同触及作者吧并未大显眼的说明。LinqToDB并没如EF那样子可以因设计好之好像来变化对应的数额库表结构。只能说脚下LinqToDB有俩栽艺术来拓展开发——一种植原生态之代码,一种植根据TT模板。原生态的代码就是数据库建了之后,配置相应的映射,然后自己工作操作。根据TT模板就是为此TT模板生成数据库对象映射。这俩种植办法笔者会越的爱慕前一样种。

LinqToDB和EF有一个相类似点。他们还生一个生死攸关之类。这个近乎拉动了颇具动作之上下文。如果说DbContext类是EF的基本,那么DataContext类便是LinqToDB的中心。DataContext类的来意跟DbContext类在EF框架之中的意图充分相近。使得只有用过EF的人口于LinqToDB有同栽亲近感。

 1 using LinqToDB;
 2 using LinqToDB.DataProvider.SqlServer;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 
 8 namespace LinqToDBExample
 9 {
10     public class DbNorthwind:DataContext
11     {
12         public DbNorthwind()
13             : base(SqlServerTools.GetDataProvider(SqlServerVersion.v2008), "Data Source=.;Initial Catalog=Northwind;User ID=sa;Password=123")
14         { 
15 
16         }
17 
18         public ITable<Products> Products { get { return this.GetTable<Products>(); } }
19 
20     }
21 }

笔者新建一个类DbNorthwind。让这个类继承DataContext类。同时增加了取Northwind数据库中dbo.Products表对应之涉嫌类属性Products。这个特性是一个ITable接口。当然跟EF的IDbSet接口有同曲同工之好。是不是当如EF找到了失散多年的兄弟。而针对投配置上那些事情仅仅怕看了事后,基本上你见面和笔者一样子淡定了多。也许你十分少用到EF的注解配置,但是这不能够代表他们俩者之间莫有相似之处。

 1 using LinqToDB.Mapping;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace LinqToDBExample
 8 {
 9     public class Products
10     {
11         [PrimaryKey, Identity]
12         public int ProductID { set; get; }
13 
14         [Column(Name = "ProductName"), NotNull]
15         public string Name { get; set; }
16     }
17 }

相了咔嚓。可以说并未呀新的学问。即使没有因此了EF,也堪起主要字被取相应之音。笔者也相信关键字PrimaryKey你在Sql
Server中必然会发因此到了。即凡主键的意思。这时候来一个简短的询问相应是一律宗很强的政工。可以给咱看他于询问是何许的变现。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace LinqToDBExample
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12             using(var db = new DbNorthwind())
13             {
14                 var query = from p in db.Products
15                             where p.ProductID > 25
16                             orderby p.Name descending
17                             select p;
18 
19                 foreach (Products product in query.ToList())
20                 {
21                     Console.WriteLine(string.Format("ProductID:{0} ------------ProductName:{1}", product.ProductID, product.Name));
22                 }
23 
24             }
25 
26             Console.ReadKey();
27         }
28     }
29 }

实践结果:

SQL Server 2

分明,LinqToDB在使的语法跟EF很相近。正而作者所说的——如果您确实不极端喜欢EF的口舌,可以尝试着用一下LinqToDB吧。也许你得观看另外一样切开天空吧说勿肯定。

假如您当上面DataContext类的构造函数用法有一点劳神。不担心吃笔者于介绍一栽。通常我们在付出之时节会用到App.config或是Web.config。而于connectionStrings节点相信大家并无生。笔者要介绍这种即使是采取安排文件来完成。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="linq2db" type="LinqToDB.Configuration.LinqToDBSection, linq2db" requirePermission="false" />
  </configSections>
  <linq2db defaultConfiguration="Aomi" />
  <connectionStrings>
    <add name="Aomi"   connectionString="Data Source=.;Initial Catalog=Northwind;User ID=sa;Password=123" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

LinqToDB自己定义一个配置类。正而上面看到的同一则。我们只要设置下面一段落配置就可以了。相信笔者应该力所能及看明白吧。就是点名默认的连天。而对connectionStrings节点的运别为作者费神了咔嚓。

<linq2db defaultConfiguration="Aomi" />

布置好了上面的音信。对应之后续DataContext类的子类就得无必须去装相应的连续字符串了。对应之代码如下。

 1 using LinqToDB;
 2 using LinqToDB.DataProvider.SqlServer;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 
 8 namespace LinqToDBExample
 9 {
10     public class DbNorthwind:DataContext
11     {
12         public ITable<Products> Products { get { return this.GetTable<Products>(); } }
13 
14     }
15 }

骨子里这种用配备的方式在EF里面也是,而面方法就是是经传播参数来规定相应的连天字符串。只不过上面在布局文件就指定了默认的连年。所以我们得以毫不指定默认的,用直白指定的方来获得连续。如下

 1 using LinqToDB;
 2 using LinqToDB.DataProvider.SqlServer;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 
 8 namespace LinqToDBExample
 9 {
10     public class DbNorthwind:DataContext
11     {
12         public DbNorthwind()
13             : base("Aomi")
14         { }
15         public ITable<Products> Products { get { return this.GetTable<Products>(); } }
16 
17     }
18 }

要大家还是不惬意的说话,笔者也不得不跪求解脱——因为作者只晓得这三种植办法了。

LinqToDB的多效果

对EF相信大家都理解没有什么长不增加的概念。至少笔者是这样子认为的。因为作者没有观看相应之增加方法。很多口说难道对一个联合数据库的集合表进行追加数据就未算是加吗(这里集合表就是起IDbSet中得来之联谊)。笔者认不是。EF好像只是发数量来没发生发生变化这个概念。你针对集合表操作就显现了多少发现变化。最后交给变化之下,EF会知道原来增加了。形式上出几许如是在用DataSet进行数据库。而LinqToDB却非是这样子,他尚是发生长这定义了。让作者举一些列子吧。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 
 7 namespace LinqToDBExample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using(var db = new DbNorthwind())
14             {
15                 Products product = new Products();
16                 product.Name = "aomi";
17 
18                 db.Insert(product);
19             }
20 
21             Console.ReadKey();
22         }
23     }
24 }

执行结果:

SQL Server 3

方做了一个简易的操作。只是可惜LinqToDB的增效果发生某些深受笔者失望。他并从未如EF那么规范。增加的时候,如果主键是全自动增加(标识),那么长成功后会把主键同步到长对象吃。如图下,增加成之后我们见到目标ProductID还是0。

SQL Server 4

对当下一点LinqToDB及是用了同样种植传统的道。扩展了一样叫InsertWithIdentity方法。增加成后回到对象主键。所以相对于点想使管增加成以后的主建同步到对应增加对象的特性被即务须用传统的方法。笔者真的一点给不了。修改如下。

 product.ProductID = Convert.ToInt32(db.InsertWithIdentity(product));

虽然上面的增加效益为笔者一时难接受。不过作者在增加点尚扩大群方。让咱得直接当相应的表属性上面操作。即是ITable接口类型的性质。这个时候如果设置对象属性值就可以了。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 
 7 namespace LinqToDBExample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using(var db = new DbNorthwind())
14             {
15                 db.Products.Value(t => t.Name, "aomi1")
16                     .Insert();
17             }
18 
19             Console.ReadKey();
20         }
21     }
22 }

瞧了咔嚓。上面由于作者之Products类才写了一个性。ProductID属性又是半自动增加。所以才生一个Value。如果要是对准几近独特性设置,就得以Value在点Value。最后在点Insert或是InsertWithIdentity。

LinqToDB的更新功能

看罢了LinqToDB的增效益下。不亮大家对LinqToDB有没有发同一种想只要错过了解冲动也?没事,让我们看一下LinqToDB对创新方面,又召开了有的啊变化。不,不可知说啊变动。应该说做了什么计划。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 
 7 namespace LinqToDBExample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using(var db = new DbNorthwind())
14             {
15 
16                 Products product = new Products();
17                 product.ProductID = 79;
18                 product.Name = "aomi update";
19 
20                 db.Update(product);
21             
22             }
23 
24             Console.ReadKey();
25         }
26     }
27 }

点立段代码做的工作特别简短——更新ProductID为79底多寡的Name值。执行成功还要更新数据库。你敢信。笔者记得当场傻眼。过因此EF的开发人员都懂要我们新建一个便的对象。注意不是于数据库中Linq出来的。而是用new关键字新建的。这时候你图更新但是EF却会变成增加。可是LinqToDB却休设有这样子的题目。这设计笔者于99瓜分。1分是笔者非承认——感觉设计思想有好几乱来。早的上笔者一直想见到LinqToDB在操作对象及可知像EF或Hibernate那样子——存在对象状态的传教。从增加的时节主键不可知同到今日新建对象更新成为来拘禁LinqToDB并不曾目标持久化这个说法。也罢,必竟是一个轻量级的ORM框架。

方的更新做法相信大家自然不会见发出啊烦感。如果新建的靶子设置主键的值之后,都能创新。那么由数据库Linq出来的数再次无用讲话了。主要是要看看一下LinqToDB给咱们带其它一个更新的做法。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 
 7 namespace LinqToDBExample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using(var db = new DbNorthwind())
14             {
15                 db.Products
16                     .Where(t => t.ProductID == 83)
17                     .Set(t => t.Name, "Update aomi")
18                     .Update();
19             }
20 
21             Console.ReadKey();
22         }
23     }
24 }

是因为长效益间的Value静态扩展方法出现,导至笔者对创新功能的Set静态扩展方法出现一些呢不飞。如果要更新多只特性的价,只要是接触多个Set就足以了。当然最终不要忘记了碰Update。更新功能的恢宏方法笔者还是于好的。相对于EF来讲,EF必须优先到数据库获得要翻新的目标。然后于修改对象的属性值才会创新。而于LinqToDB来讲,只要一步到位。

LinqToDB的删减功能

在押罢了加及换代,显然不可知忘怀了拘留一下LinqToDB在剔除方面是怎么做的。正而上面所摆的LinqToDB并无目标状态就一个说法。所以下的代码删除成功了呢非会见认为意外。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 
 7 namespace LinqToDBExample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using(var db = new DbNorthwind())
14             {
15                 Products product = new Products();
16                 product.ProductID = 79;
17 
18                 db.Delete(product);     
19             }
20 
21             Console.ReadKey();
22         }
23     }
24 }

别一样种做法:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 
 7 namespace LinqToDBExample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using(var db = new DbNorthwind())
14             {
15                 db.Products.Where(t => t.ProductID == 83).Delete();
16             }
17 
18             Console.ReadKey();
19         }
20     }
21 }

点的俩种做法。笔者十分淡定的飘过。不过到是验证了一个题材——增删改一般都产生俩栽艺术。一栽是起IDataContext接口及扩张出来的计。一种是于IQueryable接口或是ITable接口扩展出来的措施。

每当支付一个大型项目的时光,对于多表操作显得家常便饭。所以各一个框架都发出谈得来处理事务的效用。同样子LinqToDB也实现了政工功能。不过他的作业让作者特别畅快,不是为他来多好。而是他更为接近原生态。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 using LinqToDB.Data;
 7 
 8 namespace LinqToDBExample
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             using(var db = new DbNorthwind())
15             {
16                 using (DataContextTransaction transaction = db.BeginTransaction())
17                 {
18                     try
19                     {
20                         int deleteID = Convert.ToInt32(db.Products.Value(t => t.Name, "aomi79").InsertWithIdentity());
21                         db.Products.Where(t => t.ProductID == 79).Delete();
22                     }
23                     catch (Exception ex)
24                     {
25                     }
26                 }
27             
28             }
29 
30             Console.ReadKey();
31         }
32     }
33 }

上面的做法用底凡自动提交业务,如果您想要团结付的业务的话,一定要装他的参数。默认事务是半自动提交业务之。如下,笔者关闭掉自动提交业务。变成手动提交了。所以传入false。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using LinqToDB;
 6 using LinqToDB.Data;
 7 
 8 namespace LinqToDBExample
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             using(var db = new DbNorthwind())
15             {
16                 using (DataContextTransaction transaction = db.BeginTransaction(false))
17                 {
18                         db.Products.Value(t => t.Name, "aomi83").Insert();
19                         int deleteID = Convert.ToInt32(db.Products.Value(t => t.Name, "aomi79").InsertWithIdentity());
20                         int count = db.Products.Where(t => t.ProductID == deleteID).Delete();
21 
22                         if (count <= 0)
23                         {
24                             transaction.RollbackTransaction();
25                         }
26                         else
27                         {
28                             transaction.CommitTransaction();
29                         }
30                 }
31             
32             }
33 
34             Console.ReadKey();
35         }
36     }
37 }

 结束语


LinqToDB框架来客好的长和特点。同样子也有外的供不应求。而笔者想啊大家介绍LinqToDB的采用的还要再度思念呢介绍大家他是啊实现之。如果按照系列被来起谬误的传教,希望大家能够原谅。可以的话,请领出来吃作者为修一下。谢谢。

 

相关文章