EF4添加多个实体(ObjectStateManager中已存在具有相同键的对象)

时间:2010-11-17 04:26:28

标签: entity-framework-4

我有一个具有很多属性的对象。一堆这些大对象将被插入到数据库中,但只有一个属性在更改。将要更改的属性不是主键。第一次SaveChanges成功,但后续的失败,“ObjectStateManager中已存在具有相同键的对象.....”。以下是代码中的流程:

    //create the entity and set the properties that don't change
    TheLargeObject obj = new TheLargeObject();
    obj.Prop1 = 
    obj.Prop2 = 
    ...
    obj.Prop20 = 

    //create a list of values that differ between each entity
    List<int> validIds = new List<int>();

    private static void SaveToDatabase(TheLargeObject obj, List<int> validIds)
    {

        foreach (int id in validIds)
        {
            //this is the only property that changes
            obj.KeyId = id;

            //make a copy - do we really need this?
            TheLargeObject newobj = new TheLargeObject();
            newobj = obj;

            using(Entities objContext = new Entities())
            {
                objContext.TheLargeObjects.AddObject(newobj); //ERROR: An object with the same key already exists in the ObjectStateManager.  
                objContext.SaveChanges();
            }
        }
    }

我刚刚开始使用EF4,所以我可能会以错误的方式解决这个问题。 感谢

1 个答案:

答案 0 :(得分:8)

我不确定你在这里做什么。主要是这句话让我感到困惑:

  

要在数据库中插入一堆这样的大对象,但只有一个属性会发生变化。

对象(即已插入)如何更改?如果它是新的,有什么可以改变的?

模型中的所有实体都有一个 EntityKey ,它通常是数据库端的主键。

当你应该做.AddObject时,我认为你做的是.Attach

以下是插入新对象的方式:

var newFoo = new Foo();
ctx.Foos.AddObject(newFoo);
newFoo.SaveChanges();

以下是更新现有对象的方式:

var existingFoo = ctx.Foos.SingleOrDefault(x => x.Id == 1); // or however you want to get it
existingFoo.Name = "Changed foo";
newFoo.SaveChanges();

或者,如果您有分离的实体:

var existingFoo = new Foo();
existingFoo.Name = "Foo name";
ctx.Foos.Attach(existingFoo);
ctx.SaveChanges();

所以,在您的示例中,我认为,您的代码应该只是:

objContext.TheLargeObjects.Attach(newObject);
objContext.SaveChanges();

简而言之,如果您有一个积极的实体已存在于数据库中,并且您已手动构建该实体,请使用.Attach。如果您有品牌打击新对象,请使用.AddObject

但是,为了安全起见 - 您可以再次获取对象,进行所需的更改,然后执行.SaveChanges()

.Attach通常用于无状态场景,例如网站,其中对象不会在请求之间保留在图形中,因此要对.Attach进行更改,或者在制作之前再次检索对象变化。

希望这能为你解决这个问题。