【问题标题】:Linq to Entities: Mixed graph of Entities, EntityKeys, Attached, and New ObjectsLinq to Entities:实体、EntityKeys、附加对象和新对象的混合图
【发布时间】:2009-10-27 03:32:19
【问题描述】:

在我的数据模型中,我的对象/表/数据之间有一个相当普遍的划分:

  • 表示系统正在完成的工作的“事务”实体。这些实体由系统创建,仅在特定上下文中重要。它们是定期动态创建的。 (旁白:这种类型的实体有合适的名称吗?)
  • “数据字典”实体表示事务实体的公共属性。这些是不定期定义的(主要是在项目开始时),并且具有更加静态的生命周期。它们通常由我创建。

因此,例如,我可能有一个 User(事务)实体和一个 UserType(数据字典)实体。

我想将数据字典实体实例的引用(硬)编码到我的代码中。这使我能够使用易于理解的语言编写业务逻辑。 (例如,我可能有一个“Plain”的 UserType 和一个“Admin”的 UserType,然后有一条规则说“仅当用户的 UserType 等于 Admin 时才允许访问”)。

我使用 LINQ-to-Entities 作为我的数据访问技术/ORM。为了实现数据字典引用,我存储了 EntityKeys。我的理解是它们与对象上下文分离,因此适合此目的。 (由于它们不包含实体状态,我也不必担心该状态会过时。)

但是,当我尝试使用 DD-EntityKey-reference 添加新的事务实体时,这给我带来了问题。继续我的例子,我正在这样做:

UserEntities userEntities = new UserEntitites()
User user = new User()
user.UserType = new UserType()
user.UserType.EntityKey = adminEntityKey
userEntities.AddToUser(user)

...这给了我以下错误:

System.InvalidOperationException :无法将对象添加到 ObjectStateManager,因为它已经有一个 EntityKey。使用 ObjectContext.Attach 附加具有现有键的对象。

如果我尝试调用 userEntities.Attach(user) 而不是 AddToUser,我会得到:

System.InvalidOperationException : 具有空 EntityKey 值的对象不能附加到对象上下文。

考虑到我正在做的新实体和先前存在的实体的混合,这两个错误都是有道理的。我不确定如何解决这个问题。有什么方法可以分离对 DD 实体的引用并将它们分配给新的附加对象,而无需我加载整个 DD 实体状态?

【问题讨论】:

    标签: .net linq linq-to-entities persistence datamodel


    【解决方案1】:

    我将尝试解释为什么会出现这些异常:

    System.InvalidOperationException :无法将对象添加到 ObjectStateManager,因为它已经有一个 EntityKey。使用 ObjectContext.Attach 附加具有现有键的对象。

    创建了新的用户和用户类型实体。 UserType 上的 EntityKey 已设置,但是当您将其传递给 userEntities.Add() 时,EF 会尝试将它们设置为 ADDED 状态。由于 UserType 有一个 EntityKey EF 意识到有问题并抛出异常。

    System.InvalidOperationException : 具有 null EntityKey 值的对象不能附加到对象上下文。

    在此异常中,UserType 一切正常,但抛出异常是因为 User 实体 - 它没有 EntityKey,因此无法附加。

    这就是我解决这个问题的方法(如果,如你所说,数据字典引用的硬编码是可以的):

    在 UserType 实体上,我会创建对 UserType id 的静态引用:

    public partial class UserType
        {
            public const int AdminUserTypeID = 1;
            public const int PlainUserTypeID = 2;
        }  
    

    在 User 实体上会有扩展器属性,以便更轻松地访问 UserType 外键:

    public partial class User
    {
        public int? UserTypeID
        {
            set
            {
               UserTypeReference.EntityKey = new EntityKey("UserEntities.UserType", "UserTypeID", value);
            }
            get
            {
                if (UserTypeReference.EntityKey == null)
                    return null;
    
                if (UserTypeReference.EntityKey.EntityKeyValues.Count() > 0)
                    return (int)UserTypeReference.EntityKey.EntityKeyValues[0].Value;
                else
                    return null;
            }
        }
    }
    

    最后,创建新用户的用例如下所示:

    using(UserEntities userEntities = new UserEntitites())
    {
        User user = new User();
        user.UserTypeID = UserType.AdminUserTypeID;
        userEntities.AddToUser(user);
        userEntities.SaveChanges()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多