【问题标题】:Entity framework: How can I use more then one context and stay synchronized?实体框架:如何使用多个上下文并保持同步?
【发布时间】:2010-07-20 12:15:02
【问题描述】:

我是 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。

我该如何解决这个问题?

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

刷新不够好,我必须在每次查询之前都这样做(我的应用程序是多线程的),这需要很多时间。

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

谢谢!

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 但是创建上下文会创建新的数据库连接,这需要时间。我的错在哪里?
    • @Mattan,是的,但最好打开连接做一些工作并关闭连接,而不是长时间打开连接。
    • @Mattan,@James,创建 ObjectContext 并创建新的数据库连接。它从池中抓起一只。 @Mattan 过早优化。为詹姆斯和@Andras +1;这是一个糟糕的设计,需要改变。
    • @Mattan,放手吧; 你错了。实例化和处置ObjectContext 不是一项昂贵的操作,并且不会 直接导致数据库连接。您是prematurely optimizing,这是您设计错误的原因。继续这种糟糕的设计,只会加重最初的错误。
    • 正如我所说,我根据您的建议更改了我的设计。我只是问了更多问题......无论如何,非常感谢!
    【解决方案2】:

    您不应该长时间持有对对象上下文的引用。

    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

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

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

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

    【讨论】:

    • 但是创建上下文会创建新的数据库连接,这需要时间。我的错在哪里?
    • 阅读我链接的文章并相信他们!您无需担心连接管理 - 所有池等都由您负责。打开上下文,进行一些记录访问/创建等,关闭上下文。
    【解决方案3】:

    请注意,可以在多个 OC 生命周期中保持数据库连接打开,即使您的提供商不会将它们汇集在一起​​。 分析后可以调整的几件事:

    1. 在实例化 OC 时显式打开 Context.Connection。防止上下文为每个查询请求新连接。

    2. 向 OC 的构造函数提供一个现有的EntityConnection。然后它将在多个 OC 生命周期中使用现有连接。

    3. 预编译 EF 查询;它们被缓存在 OC 中。预编译它们允许缓存跨越多个 OC 实例。

    同样,OC 构造函数并不昂贵。您必须首先分析并找到缓慢的部分。解决这个问题,而不是 OC;它没有坏。

    【讨论】:

      【解决方案4】:

      正如@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); 
      

      【讨论】:

        猜你喜欢
        • 2017-12-22
        • 2015-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多