实体框架:如何使用多个上下文并保持同步?

时间:2010-07-20 12:15:03

标签: c# database visual-studio oracle entity-framework

我是EntityFramework的新手。

我的应用程序有一个上下文对象实例池(每个上下文与数据库有1个连接)。

问题在于,当我更新对象(并调用SaveChanges)时,数据会在数据库和更新上下文中更新,但是当我从其他实例中选择时,它会获取所选对象的旧数据。

示例:

让我们想象一个名为tbl的表。

该表有2列:id和data。

有1行:id = 1,data = 2.

EFContext context1 = new EFContext();      
EFContext context2 = new EFContext();      
var obj1 = context1.tbl.Where(a => a.id == 1);      
var obj2 = context2.tbl.Where(a => a.id == 1);      
obj2.data = 10;      
context2.SaveChanges(); 
var obj3 = context1.tbl.Where(a => a.id == 1); 

执行这些行后,obj3.data包含2而不是10。

我该如何解决这个问题?

每次我想访问数据库时,我都不想创建上下文实例。

刷新不够好我必须在每次查询之前执行此操作(我的应用程序是多线程的),并且需要花费很多时间。

如果我有办法让实体框架在每次尝试选择时都执行查询,那就太棒了。

谢谢!

4 个答案:

答案 0 :(得分:5)

您需要重新考虑您的设计。上下文非常轻量级,通常每个事务或工作单元创建一个上下文。我处理数据库交互时经验丰富的经验法则是尽可能晚地打开连接并尽快关闭它们,在这种情况下,您将不必要地打开多个数据库连接。

您应该考虑为问题应用更好的设计模式,请查看Repository and Unit of Work pattern

答案 1 :(得分:3)

你不打算在很长一段时间内持有对象上下文的引用。

http://blogs.microsoft.co.il/blogs/gilf/archive/2010/02/07/entity-framework-context-lifetime-best-practices.aspx

http://blogs.msdn.com/b/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx

第二个也指出:

  

线程安全:   如果您尝试重用ObjectContext,您应该知道它不是线程安全的,即类似于标准的.NET集合类。如果您从许多线程(例如Web请求)访问它,则需要确保手动同步访问。

所以,基本上,你将不得不锁定整个上下文。相反,您可以简单地为每个线程使用一个实例(根据所描述的最佳实践创建)并让数据库处理并发问题。更好的是,use transactions

尽管尝试保持上下文长时间打开以节省创建/处理等是很诱人的 - 但在实践中,您应该在需要时打开和关闭上下文。

由于您可以从上下文中获取对象并在以后将其重新附加到另一个上 - 这对于Linq to SQL来说很难(如果不是不可能的话),这使得EF变得更容易了。

所以基本上,不要这样做:)

答案 2 :(得分:0)

答案 3 :(得分:-1)

正如@Andras Zoltan所说:你并不打算在很长一段时间内持有对象背景的引用。

EFContext context1 = new EFContext();      
EFContext context2 = new EFContext();      
var obj1 = context1.tbl.Where(a => a.id == 1);      
var obj2 = context2.tbl.Where(a => a.id == 1);      
obj2.data = 10;      
context2.SaveChanges(); 
EFContext context3 = new EFContext();   //new context
var obj3 = context3.tbl.Where(a => a.id == 1);