学习Linq to SQL也有一段时间了,感叹它做为ORM虽然简单但是功能效率都还不错,从编译器和语言层面支持上来看,它是其他ORM工具不能比的。Linq to SQL中运用了很多模式对自身的效率进行优化,其实这些模式是作为一个优秀ORM工具必备的,下面我将所我知道已经在Linq to SQL中实现的模式总结如下(如果要知道这些模式的具体内容,可以参考《企业应用架构模式》)。
1. A Unit of Work(工作单元模式)
该模式主要用来跟踪对象的状态,比如从数据库里取出数据构成对象,这时候对象的值与数据库的数据是完全相同的,这些对象被标志为干净的(New)。当程序对某些对象的属性进行了修改后,这些对象被标志为脏的(Dirty)。在Linq to SQL中,使用基类为TrackedObject的对象来进行跟踪这些实体对象的状态改变(现在版本中只有StandardTrackedObject类继承了TrackedObject类)。当SubmitChanges时,遍历保存了所有TrackedObject对象的集合,根据它们自身的状态(如IsNew,IsDeleted,IsModified等)进行相应的操作。 这里使用Dictionary来保存TrackedObject,以实体对象为key,以TrackedObject对象为值,保证它们是一一对应的。
2. Identity Map (标志映射模式)
该模式主要用来缓存已经读取过的对象,避免重复加载。如果我们以主键为条件进行查询,不管查询多少次,只有第一次是对数据库提交了查询,而后面查询出来的对象都是缓存的对象,我以前的文章中有提到,如Linq to SQL之查询和添加。在Linq to SQL中,使用IdentityCache的集合对实体对象进行缓存(private class IdentityCache<T, K> 它并没有直接包装使用Dictionary等,而是自己实现的hash查找及添加算法,不知道为什么要重新写一遍)。
3. Lazy Load (延迟加载模式)
该模式解决的是用什么就取什么的问题,而不是一次就把数据全部取出来不管你需不需要。实现这种模式主要有四种方法:延迟初始化、虚代理、值保存对象和重影。Linq to SQL用最简单的延迟初始化的方法来实现该模式。当我们把实体对象的某属性标志为Delayed Loading时,该属性被声明为System.Data.Linq.Link<T>类型而不是通常的T类型,使用该值的时候大概这样:
if(this.value == null)
this.value = getValueFromDB();
return this.value;
当然这只是简单的逻辑,具体实现要复杂一些。
其次对于集合类型的属性,比如Customer中包含Order的集合,以集合为单元进行延迟初始化而不是具体的每个对象。意思是使用该集合的时候一次性把所有集合数据取出来,这样能够有效解决加载波动的问题。想想看,如果每使用一个集合中的对象时才去到数据库中查询,会产生大量的数据库连接查询,反而使得效率降低。