在他关于 DbContext 的书中,@RowanMiller 展示了如何使用 DbSet.Local 属性来避免 1.) 不必要的数据库往返和 2.) 在应用程序中传递集合(使用例如 ToList() 创建)(第 24 页)。然后我尝试遵循这种方法。但是,我注意到从一个使用 [} – 块到另一个, DbSet.Local 属性变为空:
ObservableCollection<Destination> destinationsList;
using (var context = new BAContext())
{
var query = from d in context.Destinations …;
query.Load();
destinationsList = context.Destinations.Local; //Nonzero here.
}
//Do stuff with destinationsList
using (var context = new BAContext())
{
//context.Destinations.Local zero here again;
//So no way of getting the in-memory data from the previous using- block here?
//Do I have to do another roundtrip to the database here to get the same data I wanted
//to cache locally???
}
那么,第 24 页的重点是什么?如果 DbSet.Local 只能在 using- 块内使用,我如何避免传递我的集合?此外,如果我使用这些短暂的上下文实例而不在后台将任何缓存数据移交给彼此,我如何从更改跟踪中受益?那么,如果上下文应该是短暂的以释放连接等资源,我是否应该为此放弃缓存?即我不能同时使用两者(短期连接但长期缓存)?所以我唯一的选择是将查询返回的结果存储在我自己的变量中,这正是第 24 页的动机中不鼓励的?
我正在开发一个 WPF 应用程序,它可能在未来也会变得多层,涉及 WCF。我知道 Julia 在她的书中有一个这样的例子,但我目前无法访问它。我在网上找到了其他几个,例如http://msdn.microsoft.com/en-us/magazine/cc700340.aspx(旧的 ObjectContext,但很好地解释了层间协作)。在那里,使用了一个长寿命的上下文(虽然提到了缺点,但没有提供这些缺点的解决方案)。不仅单个 Destinations.Local 会丢失,因为您肯定知道查询获取的所有其他实体也是如此。
[编辑]:在阅读了 Julia Lerman 的书之后,似乎可以归结为 EF 默认没有二级缓存;但是,通过一些(我认为是相当大的)努力,可以添加第 3 方缓存解决方案,正如本书和 MSDN、codeproject 等的各种文章中所描述的那样。
如果在 DbContext 书中关于 DbSet.Local 的部分中提到了这个问题,我将不胜感激,因为它实际上是一级缓存,在 using {} 块结束时被销毁(只是我的建议,使其对读者)。在第一次阅读之后,我的印象是 DbSet.Local 总是会在第二个 using {} 块中返回相同的引用(单例样式),尽管有新的 DbContext 实例。
但我仍然不确定二级缓存是否适合我的 WPF 应用程序(正如 Julia 在她的分布式应用程序文章中提到的二级缓存)?或者是通过 using {} 块中的一个或一些查询将我的域模型的聚合根实例(DDD,Eric Evans)放入内存的方法,处理 DbContext 并只保存对聚合实例的引用,这个避免长期存在的上下文?如果您能帮助我做出这个决定,那就太好了。
http://msdn.microsoft.com/en-us/magazine/hh394143.aspx http://www.codeproject.com/Articles/435142/Entity-Framework-Second-Level-Caching-with-DbConte http:// blog.3d-logic.com/2012/03/31/using-tracing-and-caching-provider-wrappers-with-codefirst/