0

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

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

因此,例如,我可能有一个 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 :具有 null EntityKey 值的对象不能附加到对象上下文。

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

4

1 回答 1

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()
}
于 2009-10-27T08:46:20.240 回答