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

发布于 2024-08-08 13:47:05 字数 1248 浏览 7 评论 0原文

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

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

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

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

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

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

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 实体状态?

In my data model I have a fairly common division between my objects/tables/data:

  • "Transactional" entities that represent the work that is being done by the system. These entities are created by the system and are only important in specific contexts. They are regularly created on the fly. (Aside: Is there a proper name for this type of entity?)
  • "Data Dictionary" entities that represent common properties of the transactional entities. These are defined irregularly (mostly at the start of the project) and have a much more static lifecycle. They are typically created by me.

So, for example, I might have a User (transactional) entity and a UserType (data dictionary) entity.

I want to (hard)code references to instances of the Data Dictionary entities into my code. This gives me the ability to code business logic with an easy-to-understand language. (So, for example, I might have a UserType of "Plain" and a UserType of "Admin", and then a rule that says "allow access only if the User's UserType equals Admin").

I'm using LINQ-to-Entities as my data access technology/ORM. To implement the Data Dictionary references, I'm storing EntityKeys. My understanding is that they're detached from the object context and so are suitable for this purpose. (As they don't contain entity state, I also don't have to worry about that state going stale.)

However, this is giving me problems when I try to add a new transactional entity with a DD-EntityKey-reference. Continuing my example, I'm doing this:

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

...and this gives me the following error:

System.InvalidOperationException : The object cannot be added to the ObjectStateManager because it already has an EntityKey. Use ObjectContext.Attach to attach an object that has an existing key.

If I try to call userEntities.Attach(user) instead of AddToUser, I get this:

System.InvalidOperationException : An object with a null EntityKey value cannot be attached to an object context.

Both of these errors make sense, given the mixing of new and preexisting entities that I'm doing. What I'm not sure about is how to get around this issue. Is there some way I can have detached references to DD-entities and assign them to new attached objects without requiring me to load the entire DD-entity state?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

勿忘初心 2024-08-15 13:47:05

我将尝试解释为什么您会遇到这些异常:

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

创建新的 User 和 UserType 实体。 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()
}

I'll try to explain why are you getting these exceptions:

System.InvalidOperationException : The object cannot be added to the ObjectStateManager because it already has an EntityKey. Use ObjectContext.Attach to attach an object that has an existing key.

New User and UserType entities are created. The EntityKey on UserType has been set but when you pass it to userEntities.Add() EF tries to set them status ADDED. Since UserType has an EntityKey EF realises something is wrong and throws exception.

System.InvalidOperationException : An object with a null EntityKey value cannot be attached to an object context.

In this exception everything is ok with UserType, but the exception is thrown because User entity - it has no EntityKey and therefore cannot be attached.

This is how I would solve this problem (if, as you say, hardcoding of data dictionary references is ok):

On UserType entity I would create static references to UserType id's:

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

On User entity there would be extender property for easier access to the UserType foreign key:

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;
        }
    }
}

Finally, the use case for creating new user would look like this:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文