ObjectStateManager 中已存在具有相同键的对象

发布于 2024-12-10 13:41:46 字数 875 浏览 0 评论 0原文

这个错误已经被问了很多。但我认为这些情况都不适用于我的具体情况,或者至少不完全适用。

我正在创建一个具有 2 个导航属性(集合)的新实体。实体和导航属性都是数据库中不存在的新实体。我的问题是,每当我尝试将实体附加到上下文时,如果任一集合具有超过 1 个元素,我就会遇到上述异常。

我在以下代码中的 Attach() 指令上收到此错误:

using (var context = new NSModel())
{
    context.Notifications.Attach(e);
    context.ObjectStateManager.ChangeObjectState(e,
    StateHelpers.GetEquivalentEntityState(e.State));

    foreach (NavigationProperty1 np in e.NavigationProperty1s)
        context.ObjectStateManager.ChangeObjectState(np,
        StateHelpers.GetEquivalentEntityState(np.State));

    foreach (NavigationProperty2 np in e.NavigationProperty2s)
        context.ObjectStateManager.ChangeObjectState(np,
        StateHelpers.GetEquivalentEntityState(np.State));

    context.SaveChanges();
    return e;
}   

该代码适用于网站,因此实体是无状态的,并且每次调用都会创建和处理上下文...

任何想法?

This error has been asked about A LOT. But none of the cases I think apply to my particular case, or at least not quite.

I am creating a new entity with 2 navigation properties that are collections. Both the entity and the navigation properties are new entities that do not exist in the database. My problem is that whenever I try to attach the entity to the context, if either of the collections has more than 1 element I get to aforementioned exception.

I am getting this error on the Attach() instruction in the following code:

using (var context = new NSModel())
{
    context.Notifications.Attach(e);
    context.ObjectStateManager.ChangeObjectState(e,
    StateHelpers.GetEquivalentEntityState(e.State));

    foreach (NavigationProperty1 np in e.NavigationProperty1s)
        context.ObjectStateManager.ChangeObjectState(np,
        StateHelpers.GetEquivalentEntityState(np.State));

    foreach (NavigationProperty2 np in e.NavigationProperty2s)
        context.ObjectStateManager.ChangeObjectState(np,
        StateHelpers.GetEquivalentEntityState(np.State));

    context.SaveChanges();
    return e;
}   

The code is for a web site so the entities are stateless and the context is created and disposed of with every call...

Any ideas?

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

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

发布评论

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

评论(1

城歌 2024-12-17 13:41:46

实体和导航属性都是新实体
数据库中不存在。

那么问题来了:为什么要使用Attach?通过使用 Attach,您可以告诉 EF 实体位于数据库中,并且 EF 会将主键属性的值视为数据库中的 PK 列值。因为这些属性必须是唯一的,一旦您有两个具有相同键值的实体,EF 就会抱怨。当您将自动生成的身份作为关键属性并且在创建实体时未设置值时,很可能会遇到这种情况。

简单的例子:

public class Parent
{
    public Parent
    {
        Children = new List<Child>();
    }

    public int Id { get; set; }
    public ICollection<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }
}

此代码……

using (var ctx = new MyContext())
{
    var parent = new Parent();
    var child1 = new Child();   // <- Id is 0
    var child2 = new Child();   // <- Id is 0 as well

    parent.Children.Add(child1);
    parent.Children.Add(child2);

    ctx.Parents.Attach(parent);  // <- exception here

    //...
}

将抛出异常,因为 EF 尝试使用相同的键 0 附加两个不同的子实例。当第二个子 child2 被附加时,它会显示:“具有相同键(即 0)的对象(即 child1)已存在于对象状态管理器”。

如果您想将整个对象图作为新实体添加到数据库中,您只需调用 context.Notifications.AddObject(e); 而不是 Attach

Both the entity and the navigation properties are new entities that do
not exist in the database.

Then the question is: Why do you use Attach? By using Attach you tell EF that the entites are in the database and EF will consider the values of the primary key properties as the PK column values in the database. Because those properties must be unique EF will complain as soon as you have two entites with the same key values. It's well possible that you have this situation when you have autogenerated identities as key properties and don't set the values when you create the entities.

Simple example:

public class Parent
{
    public Parent
    {
        Children = new List<Child>();
    }

    public int Id { get; set; }
    public ICollection<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }
}

This code ...

using (var ctx = new MyContext())
{
    var parent = new Parent();
    var child1 = new Child();   // <- Id is 0
    var child2 = new Child();   // <- Id is 0 as well

    parent.Children.Add(child1);
    parent.Children.Add(child2);

    ctx.Parents.Attach(parent);  // <- exception here

    //...
}

... will throw your exception because EF tries to attach two different child instances with the same key 0. When the second child child2 will get attached it says: "An object (namely child1) with the same key (namely 0) already exists in the ObjectStateManager".

If you want to add the whole object graph as new entities to the database you could just call context.Notifications.AddObject(e); instead of Attach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文