我有一个断开连接的实体框架图,它被发送到客户端并随更新一起返回。其中一个更新可能会替换图中间的实体。当我尝试替换它时,我收到 InvalidOperationException 并显示以下消息:
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
为简单起见,模型看起来像这样:
导致异常的代码如下所示:
// Create a tree of objects
Root root = new Root() { Id = 1 };
Branch origBranch = new Branch() { Id = 3 };
Twig onlyTwig = new Twig() { Id = 5 };
Leaf onlyLeaf = new Leaf() { Id = 7 };
onlyTwig.Leaves.Add(onlyLeaf);
origBranch.Twigs.Add(onlyTwig);
root.Branches.Add(origBranch);
// Store the structure in the database using the container
using (Pot container1 = new Pot())
{
container1.Roots.Add(root);
container1.SaveChanges();
}
// Create a new Branch to replace the original
Branch newBranch = new Branch() { Id = 11 };
// Add the Twig from the original object
newBranch.Twigs.Add(onlyTwig);
using (Pot container2 = new Pot())
{
container2.Roots.Attach(root);
// Replace the branch
root.Branches.Remove(origBranch);
root.Branches.Add(newBranch);
container2.SaveChanges(); // THROWS EXCEPTION !!
}
我想通过删除旧实体,然后添加一个新的实体,我将满足“新关系必须定义...”标准,但它失败了。在我们的例子中,在数据库中使列可以为空可能会导致其他问题,第一个问题就是冒着数据库完整性的风险。那通常如何处理?
我解决了部分问题,主要是欺骗实体框架,使其相信它正在进行更新,而不是用新项目替换项目。解决方案的关键是设置相同的主键值,然后将实体状态设置为修改替换代码将在下面发布。
// Create a new Branch to replace the original
// Make sure to use the id from the original saved object
Branch newBranch = new Branch() { Id = origBranch.Id };
// Add the Twig from the original object
newBranch.Twigs.Add(onlyTwig);
// Replace the original branch with the new branch
root.Branches.Remove(origBranch);
root.Branches.Add(newBranch);
using (Pot container2 = new Pot())
{
// Attach the graph to the container. The default state is unchanged.
container2.Roots.Attach(root);
// Trick entity framework into thinking the new branch with the
// same primary key is the original item with modifications
container2.Entry(newBranch).State = EntityState.Modified;
container2.SaveChanges();
}
但是,有时候用全新的实体替换实体,所以我仍然需要一个答案,如何 删除然后添加 。