我有一个具有很多属性的对象。一堆这些大对象将被插入到数据库中,但只有一个属性在更改。将要更改的属性不是主键。第一次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,所以我可能会以错误的方式解决这个问题。 感谢
答案 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
进行更改,或者在制作之前再次检索对象变化。
希望这能为你解决这个问题。