4

在他关于 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/

4

1 回答 1

0

Local属性提供“此集中所有已添加、未更改和已修改实体的本地视图”。与所有更改跟踪一样,它特定于您当前使用的上下文。

DB Context 是一个用于加载数据和准备更改的工作区。

如果两个用户同时添加更改,他们必须在保存之前不知道其他更改。他们可能会丢弃他们准备好的更改,这会突然给其他其他用户带来问题。

数据库上下文确实应该是短暂的,但在必要时可能比超短更长。另请考虑,如果您不加载和丢弃数据而只添加您将保存的更改,则可能无法通过保持资源短暂来节省资源。但这不仅与资源有关,还与 DB 状态可能会发生变化有关,而 DB 上下文仍处于活动状态并已加载数据;这对于更长寿的环境可能很重要。

如果您还不知道要立即保存到数据库中的所有相关更改,那么我建议您不要使用 DB 上下文将更改存储在内存中,而是存储在代码中的数据结构中。

您当然可以在没有活动数据库上下文的情况下使用实体对象来执行此操作。如果您没有另一个合适的数据类并且不想创建一个,或者决定准备其中的更改更有意义,那么这是有道理的。然后,您可以使用DbSet.Attach将实体附加到数据库上下文,以便在您准备好时保存更改。

于 2019-08-07T14:53:08.527 回答