C# 附加类型为'的实体;X';失败,因为另一个相同类型的实体
我在代码中偶然发现了一个奇怪的错误。以前是有效的,但现在有时有效 我正在使用EF6编辑具有某些关系的实体。 要不编辑关系,我将其“附加”(参见示例代码) 我编辑了这些名字以保持简单 下一行C# 附加类型为'的实体;X';失败,因为另一个相同类型的实体,c#,entity-framework,C#,Entity Framework,我在代码中偶然发现了一个奇怪的错误。以前是有效的,但现在有时有效 我正在使用EF6编辑具有某些关系的实体。 要不编辑关系,我将其“附加”(参见示例代码) 我编辑了这些名字以保持简单 下一行 Context.Cs.Attach(b.C); 抛出此错误: 附加类型为“C”的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的
Context.Cs.Attach(b.C);
抛出此错误:
附加类型为“C”的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”
引入这一行是因为所有C实体都是静态实体。我从不希望创建一个C。如果我删除这行,每次我都会在a中添加B;创建一个C。这是不可取的
额外信息:A有一个B的列表
B有一个C
这个EditA()方法在我的软件中的多个位置被调用。只有在循环(导入)中调用该方法时,才会出现此错误。处理第一条记录时没有问题。但是在第一次之后,我在记录中发现了错误 我读过这些问题和答案,但它们对我不起作用:
请看下面的链接 如果您知道数据库中已经存在一个实体,但可能已经对其进行了更改,那么您可以告诉上下文附加该实体并将其状态设置为“已修改”。例如:
var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };
using (var context = new BloggingContext())
{
context.Entry(existingBlog).State = EntityState.Modified;
// Do some more work...
context.SaveChanges();
}
注意:您不必对所有对象(A、B和C)都这样做,只需对A
编辑1
根据您的评论,尝试以下方法:
//check if
var _b = Context.Bs.Find(ThisIsB.BId);
if (_b != null)
//b doesn't exist, then add to the context
//make sure that the primary key of A is set.
//_b.PrimaryKeyOfA = someValue;
Context.Bs.Add(_b);
else
//b already exists, then modify the properties
//make sure that the primary key of A is set.
Context.SaveChanges();
编辑2
我没有测试,但它应该可以工作
public void EditA(A ThisIsA, B ThisIsB)
{
using (var Context = new LDZ_DEVEntities())
{
//if A has been loaded from context
//dont attach it
//if it has been created outside of the context
//Context.Entry(ThisIsA).State = EntityState.Modified;
var _b = Context.Bs.Find(ThisIsB.BId);
if (_b == null)
{
_b = ThisIsB;
}
ThisIsA.Bs.Add(_b);
Context.SaveChanges();
}
}
我修好了
在法比奥·卢兹的回答中,他说:
//如果已从上下文加载
//不要附加它//如果它是在上下文之外创建的
//Context.Entry(ThisIsA.State=EntityState.Modified
这让我思考,因此我将代码编辑为:
public void EditA(A ThisIsA, B ThisIsB)
{
using (var Context = new LDZ_DEVEntities())
{
var a = Context.As.Find(ThisIsA.AId);
//var b = Context.Bs.FirstOrDefault(x => x.BId == ThisIsB.BId);
var b = Context.Bs.Find(ThisIsB.BId);
if (b != null)
Context.Bs.Attach(b);
else
b = ThisIsB;
if (b.C != null)
Context.Cs.Attach(b.C);
a.Bs.Add(b);
Context.SaveChanges();
}
}
变更摘要:- 更改了FirstOrDefault以查找
- 从上下文中获取信息
特别感谢法比奥·卢兹。没有你的帮助,我不可能做到这一点 另一种方法(取决于您的情况)是简单地分离实体状态
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Modify(Model model)
{
if (model.Image == null)
{
Model item = db.Model.Find(model.Name);
// Get the Content needed:
model.Image = item.Image;
// Detach the Comparison State:
db.Entry(item).State = EntityState.Detached;
}
if (ModelState.IsValid)
{
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
这样做:db.Entry(item).State=EntityState.Detached代码>EntityFramework的状态仍然完好无损,您可以将更改保存到数据库(db)中
希望这有帮助 如果A有一个B列表,B有一个C,您只需要附加A。B和C将自动插入…C是静态实体。我从不想插入它们。只有在B不存在的情况下才需要插入B。你所说的“静态实体”是什么意思?根据您的代码,有一个C实体的数据集。它们怎么可能是“静态的”?静态的,就像在中一样,有一组C实体。那些永远不会被创建/更新/删除的相关帖子可能会有所帮助:不幸的是,这并没有解决问题。该方法用于将a B添加到a。。所以我只想登记A和B之间的变化。。如果B不存在。。B将被创建(发生在A.Bs.Add(B)中)。查看编辑1如果您查看我的示例代码,您可以看到我已经在执行类似于您的编辑的操作。当我尝试附加C时抛出错误。或者您认为它是由其他原因引起的吗?我相信我们缺少了一些东西。你能给我解释一下你到底想做什么吗?我这么说是因为你的编辑方法有3个参数,我觉得很奇怪。。。没必要,我理解这种混乱。C不是作为参数存在的,我在那里添加了它,看看它是否可以解决这个问题。我已经编辑了我问题中的代码。欢迎你,伙计!谢谢你的夸奖。将自己的帖子标记为将来帮助他人的答案:这对我真的很有帮助-我在一个单独的变量中加载了我正在编辑的实体,没有想到变更跟踪器会跟踪不同的版本并比较两者。。一旦我删除了另一个引用,那么对EntityState.Modified的更改就非常有效。谢谢。没问题,keithl8041,帮我把这篇文章投到有用的地方,这样我们就能帮助人们找到可能对他们有帮助的答案
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Modify(Model model)
{
if (model.Image == null)
{
Model item = db.Model.Find(model.Name);
// Get the Content needed:
model.Image = item.Image;
// Detach the Comparison State:
db.Entry(item).State = EntityState.Detached;
}
if (ModelState.IsValid)
{
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}