【问题标题】: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

标签: c# .net entity-framework


【解决方案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 上有一个很好的常见问题解答

      【讨论】:

      【解决方案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 应用程序,您是绝对正确的。当我三年前回答这个问题时,我怀疑三年前我是否已经仔细阅读过它以意识到这一点:-)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多