01 Customer customer = null;
02
03 using (var context = CreateNorthwnd())
04 {
05 var option = new DataLoadOptions();
06 // disabled the deferred loading
07 context.DeferredLoadingEnabled = false;
08 // specify the association in needed
09 option.LoadWith<Customer>(c => c.Orders);
10 context.LoadOptions = option;
11
12 customer = context.Customers.First();
13 }
14
15 customer.City = "Beijing";
16
17 using (var context = CreateNorthwnd())
18 {
19 context.Customers.Attach(customer);
20 context.Refresh(RefreshMode.KeepCurrentValues, customer);
21 context.SubmitChanges();
22 }
首先我们关闭了DataContext的延迟加载,并且通过DataLoadOption显式指定了需要加载的关联数据,这样的做法不但解决Attach的问题,而且还避免了在N-Tier Application中由于延迟加载所可能导致的异常。
LINQ2SQL最佳实践
文章最后罗列一些我自己总结的应用LINQ2SQL的心得。
1、建议通过using来使用DataContext对象,这样当操作完毕立即销毁DataContext对象。默认状态下(ObjectTrackingEnabled=true),DataContext将在内存中保存查询对象的副本,如果长时间保持 DataContext对象,会造成内存不必要的占用。
2、对于仅查询的操作,设ObjectTrackingEnabled=false,关闭对象跟踪有助于提高DataContext的查询性能,这也是所谓的只读DataContext。再根据所需数据,设置DataLoadOption.AssociateWith()、 DataLoadOption.LoadWith(),可实现高效的查询。
3、当用LINQ2SQL编写N-Tier Application时,建议关闭延迟加载,因为这带来的麻烦远远大于好处。注意当ObjectTrackingEnabled=false时,延迟加载是不可用的,相当于DataContext.DeferredLoading=false。
4、Attach(entity, false) + DataContext.Refresh(RefreshMode.KeepCurrentValues, entity) + SubmitChanges(),实现断开对象的更新,这就避免了DuplicateKey的问题,如上面给出的代码所示。
麒麟的帖子引发了不少讨论,挺有趣的:
1、“方法签名中不出现linq to sql的实体,方法代码块中肯定要出现的。我看人家的开源项目都是在访问数据库的时候再将DomainModel转化为linq to sql的Entity,这样使用的linq to sql。”
对于N-Tier Application,DomainModel(领域对象)的应用范围在Presentation Layer和Business Layer之间的层次,而LINQ生成的POCO类属于DataModel,应用范围在整个N-Tier。在概念上DomainModel和 DataModel是不同的,但是在大多数的3-tier应用中,DomainModel和DataModel是同一个类——实体类。至于为什么“人家开源项目”会这样做,我想大多数原先并不是用LINQ开发,后来移植过来的吧?