Linq to Entities:实体,EntityKeys,附加和新对象的混合图

时间:2009-10-27 03:32:19

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

在我的数据模型中,我的对象/表/数据之间存在相当普遍的区别:

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

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

我希望(硬)将对数据字典实体实例的引用编码到我的代码中。这使我能够使用易于理解的语言对业务逻辑进行编码。 (例如,我可能有一个UserType为“Plain”,UserType为“Admin”,然后是一个规则,“只有当User的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(用户)而不是AddToUser,我会得到这个:

  

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

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

1 个答案:

答案 0 :(得分: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;
    }  

在用户实体上会有扩展程序属性,以便更轻松地访问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()
}