如何使用实体框架关联来自多个上下文的对象

Posted

技术标签:

【中文标题】如何使用实体框架关联来自多个上下文的对象【英文标题】:How to relate objects from multiple contexts using the Entity Framework 【发布时间】:2010-09-14 14:40:36 【问题描述】:

我对实体框架非常是新手,所以请多多包涵...

如何将来自不同上下文的两个对象关联在一起?

下面的例子抛出了以下异常:

System.InvalidOperationException: 两个对象之间的关系 无法定义,因为它们是 附加到不同的 ObjectContext 对象。

void MyFunction()

    using (TCPSEntities model = new TCPSEntities())
    
        EmployeeRoles er = model.EmployeeRoles.First(p=>p.EmployeeId == 123);
        er.Roles = GetDefaultRole();
        model.SaveChanges();
     


private static Roles GetDefaultRole()

    Roles r = null;
    using (TCPSEntities model = new TCPSEntities())
    
        r = model.Roles.First(p => p.RoleId == 1);
    
    return r;

使用一个上下文不是一种选择,因为我们在 ASP.NET 应用程序中使用 EF。

【问题讨论】:

为什么将数据上下文类型命名为TCPSEntities,为什么将数据上下文对象命名为model?您可能会考虑不使用new,而是将预先构造的数据上下文或数据上下文工厂传递给函数。您可能还考虑使用Enumerable.SingleOrDefault 而不是Enumerable.First 【参考方案1】:

您将不得不使用相同的上下文(您可以将上下文传递给 getdefaultrole 方法)或重新考虑关系并扩展实体。

编辑:想要添加这是针对提供的示例,使用 asp.net 将需要您充分考虑您的上下文和关系设计。

你可以简单地传递上下文.. IE:

void MyFunction()

    using (TCPSEntities model = new TCPSEntities())
    
        EmployeeRoles er = model.EmployeeRoles.First(p=>p.EmployeeId == 123);
        er.Roles = GetDefaultRole(model);
        model.SaveChanges();
     



private static Roles GetDefaultRole(TCPSEntities model)

    Roles r = null;
    r = model.Roles.First(p => p.RoleId == 1);
    return r;

【讨论】:

【参考方案2】:

您可以在此处使用的另一种方法是将对象从一个上下文中分离出来,然后将它们附加到另一个上下文。这有点小技巧,它可能不适用于您的情况,但它可能是一种选择。

    public void GuestUserTest()
    
        SlideLincEntities ctx1 = new SlideLincEntities();
        GuestUser user = GuestUser.CreateGuestUser();
        user.UserName = "Something";
        ctx1.AddToUser(user);
        ctx1.SaveChanges();

        SlideLincEntities ctx2 = new SlideLincEntities();
        ctx1.Detach(user);
        user.UserName = "Something Else";
        ctx2.Attach(user);
        ctx2.SaveChanges();
    

【讨论】:

【参考方案3】:

是的 - 实体框架 V1 不支持跨 2 个或更多上下文工作。

以防万一你还没有找到它,在http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx EF 上有一个很好的常见问题解答

【讨论】:

旧帖子,但参考链接很好...现在在ef-faq.org维护。 立即制作social.technet.microsoft.com/wiki/contents/articles/…。【参考方案4】:

据我了解,您希望尽可能少地实例化您的模型(通过“new XXXXEntities()”位)。根据 MS (http://msdn.microsoft.com/en-us/library/cc853327.aspx) 的说法,这是一个相当大的性能损失。因此将其包装在 using() 结构中并不是一个好主意。我在我的项目中所做的是通过始终提供相同上下文实例的静态方法来访问它:

    private static PledgeManagerEntities pledgesEntities;
    public static PledgeManagerEntities PledgeManagerEntities
    
        get 
        
            if (pledgesEntities == null)
            
                pledgesEntities = new PledgeManagerEntities();
            
            return pledgesEntities; 
        
        set  pledgesEntities = value; 
    

然后我像这样检索它:

    private PledgeManagerEntities entities = Data.PledgeManagerEntities;

【讨论】:

这称为单例模式。 有几件事:(1) 我认为您必须小心执行此操作,因为上下文将跟踪它已加载的任何实体的方式,从而导致实例变大。 (2) 您引用的文章还指出:“在大多数情况下,您应该在 using 语句中创建一个 ObjectContext 实例”。 (3) 如果一次调用 SaveChanges() 失败,那么所有后续调用都可能失败,除非您分离失败的实体。如果您有多个调用者使用相同的上下文,那么您可能会陷入混乱。 (4) ObjectContext 不是线程安全的 这对 Web 应用程序来说绝对不安全,性能提升可以忽略不计。除了特殊情况,您通常应该在每个业务操作中使用一个上下文。这通常意味着每个页面/窗口使用一个上下文。 @Kurian - 对于 ASP.NET 应用程序,您是绝对正确的。当我三年前回答这个问题时,我怀疑三年前我是否已经仔细阅读过它以意识到这一点:-)。

以上是关于如何使用实体框架关联来自多个上下文的对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用对象上下文在实体框架中使用批量插入?

如果您想通过 Core Data 使用多个实体,您需要为每个实体提供一个托管对象上下文吗?

在ug里如何把一个实体复制成另一个,而且没有关联性

如何附加不是来自数据库的实体框架对象?

实体框架在运行时创建多个表 C#

在实体框架中将对象树附加到对象上下文