您的位置:首页 > 数据库

LINQ TO SQL 注意事项

2012-01-29 16:49 316 查看
LINQ,语言集成查询(Language-Integrated Query)。是VS 2008中引入的新特性,为C#和VB提供了强大的查询功能。在网上大家对LINQ褒贬不一,但我觉得它至少可以做到编写更少的代码创建完整的应用,缩短了开发周期,这一点就很吸引我这种懒人了!我也知道LINQ比起ADO.NET性能上会差一些,但我做的都不是什么大型项目,这点差距应该是可以忽略不计的。一直以来,主要接触的是LINQ to SQL,虽然并没有玩转它,也还是积累了一点东西。
不要将DataContext单例化

单个DataContext最大的问题就是SubmitChanges造成当前线程和数据库的数据不同步。DataContext不是线程安全的对象,由于它会缓存所有的数据操作,当A线程的数据修改到一半,它可能被B线程在调用SubmitChanges时提交了,这个问题在开发时不容易被发现。之前我在项目中用了单例模式创建DataContext,导致出现用户反应“为什么我在这篇文章的评论会跑到别的文章下面去了?!”之类的问题,正是因为这个原因。DataContext是LINQ to SQL框架的主入口点,它拥有所有表的映射让我觉得会占用很多资源,所以我用单例模式创建它。有人通过分析源代码得出结论:“DataContext并没有占用多么庞大的资源,无非就是一个DbConnection和一些映射对象而已。”,我才知道那只是映射,没有任何数据。MSDN上也提示:“请不要试图重用DataContext的实例。每个DataContext都会保持对应一个特定编辑/查询会话的状态(包括标识缓存)。若要获取基于数据库当前状态的新实例,请使用新的DataContext。”

因此,DataContext是不应该被单例化或是静态化的。DataContext是轻量级的资源,创建它不需要很大的开销,最佳实践是为每个操作创建新的DataContext实例。

禁用ObjectTrackingEnabled

DataContext的ObjectTrackingEnabled设为false这样减少了要跟踪的项目,可以提高检索时的性能,但禁用对象跟踪时,要特别注意:

(a)只是推荐在查询的情况下禁用;

(b)必须在执行查询前禁用;

(c)禁用之后不能再调用Attach和SubmitChanges方法。

添加IsDbGenerated=true

默认情况下,LINQ添加对象时,数据库中设置的默认值会失效。例如:ModifiedTime是数据库中使用getDate()为默认值的,如果没有为对应的实体属性添加IsDbGenerated=true, 则数据库中的getDate()将失效。

为实体添加RowVersion成员

对于在不同的DataContext之间,使用Attach方法来更新数据,但是Attach方法不能附加一个修改过的实体,除非该实体包含RowVersion成员。

实现RowVersion成员的方法有两种:

(1)为数据库表定义一个timestamp列;

(2)在表主键所对应的实体属性上,定义IsVersion=true特性。

注意,两种方法不能同时使用,否则将抛出InvalidOperationException:成员“System.Data.Linq.Binary timeStamp”和“Int32 XXId”都标记为行版本。

LINQ默认采用“乐观式并发”的策略处理更新数据时的并发冲突。在乐观式并发中,Where子句不只是包含主键字段,还会加入除更新字段外的所有字段,作为Update语句的Where条件。在调用DataContext的SubmitChanges方法时,若Update语句在更新过程中产生了冲突,就会抛出“找不到行或行已更改”的异常。在默认情况下,实体属性的UpdateCheck都设置为UpdateCheck.Always,表示LINQ to SQL将用该属性检查乐观式并发。乐观式并发的参数数量过多,会导致不必要的性能消耗,因此需要修改映射规则,只让部分属性参与到并发检查中。

若在数据表中有timestamp列,实体属性的UpdateCheck会默认设置为UpdateCheck.Never,若使用IsVersion作为更新检查依据,则必须在实体属性上(主键除外)手动设置UpdateCheck.Never来避免更新检查,但是数据库表结构更新,再重新生成dbml的话,手动设置的IsVersion=true和UpdateCheck.Never都将消失不见。所以推荐使用timestamp作为更新检查依据,我想主键列和timestamp列还是各司其职比较好些。为所有数据表创建一个timestamp列,在处理并发的时候,LINQ to SQL就不需要检查所有的字段,这样可以提高系统的性能。

AutoSync特性的作用

对于表主键对应的实体属性,AutoSync会默认设置为AutoSync.OnInsert,它的作用就是Insert一个对象时,当调用DataContext的SubmitChanges方法后,主键对应的属性值会被自动填充。

不需要手动执行DataContext的Dispose方法

DataContext在SubmitChanges方法的finally块中调用了SqlConnection.Close方法;而执行查询的DataContext.ExecuteQuery方法到最后也会调用SqlConnectionManager.ReleaseConnection方法。在我们手动执行DataContext.Dispose时,主要工作已经执行完了,并且SqlConnectionManager.ReleaseConnection方法所执行的内容比SqlConnection.Close方法要多。

因此,在使用LINQ to SQL时,完全没必要手动执行DataContext.Dispose方法或是使用using语句。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: