C# EF仅第一次将对象附加到foreach工作中的上下文
我有一个需要附加到上下文的对象列表,以便跟踪更改并随后保存更改,但是迭代项的foreach只在方法结束后第一次执行。 我确信这些项目已经存在于数据库中 我尝试调用C# EF仅第一次将对象附加到foreach工作中的上下文,c#,.net,wpf,entity-framework,C#,.net,Wpf,Entity Framework,我有一个需要附加到上下文的对象列表,以便跟踪更改并随后保存更改,但是迭代项的foreach只在方法结束后第一次执行。 我确信这些项目已经存在于数据库中 我尝试调用.Attach()方法,并将条目状态设置为Unchanged 受保护的覆盖任务SetViewModelPropertiesAsync() { 选择editems.ForEach(l=> { //上下文。附件(l); Context.Entry(l).State=System.Data.Entity.EntityState.Unchan
.Attach()
方法,并将条目状态设置为Unchanged
受保护的覆盖任务SetViewModelPropertiesAsync()
{
选择editems.ForEach(l=>
{
//上下文。附件(l);
Context.Entry(l).State=System.Data.Entity.EntityState.Unchanged;
//在第一次迭代之后,方法结束
});
返回base.SetViewModelPropertiesAsync();
}
我希望所有的项都被添加到上下文中,但是在foreach循环的第一次迭代之后,会中断该方法并继续到下一次,甚至不会给出异常
编辑:
在执行Attach或EntityState时,foreach后面有更多的代码被跳过。
如果我对这两个代码都进行了注释,则代码将正确执行该行为听起来确实像是抛出了异常。这是关于
List.ForEach()
的一个巨大的危险信号,也是我从不使用它的主要原因。如果将代码更改为:
foreach(var item in SelectedItems)
{
Context.Pap_Pedido_ODP.Attach(item);
Context.Entry(item).State = System.Data.Entity.EntityState.Unchanged;
}
。。。您现在至少应该看到阻塞代码的异常。在上下文之间附加/分离实体是混乱的,我个人能够证明这一点的场景非常少。您正在处理对实体的引用。这意味着:
foreach(var item in SelectedItems)
{
if(Context.Pap_Pedido_ODP.Local.Contains(item))
{ // This exact instance is already associated to the Context.
// We shouldn't need to copy anything across or do anything...
}
else
{
var existingItem = Context.Pap_Pedido_ODP.Local.SingleOrDefault(x => x.Id == item.Id);
if(existingItem != null)
{ // A different instance matching this one already exists in the context,
// Here if item represents changes we would need to copy changes across to existingItem...
}
else
{ // Item is not associated, safe to attach.
Context.Pap_Pedido_ODP.Attach(item);
// ...
}
}
}
现在还没有结束。如果“项”包含对其他实体的引用,则每个实体都将自动更新。如果其中一些已与上下文关联,则可能会导致问题。这可能是由于DbContext的生存期太长或引用实体的同一实例的多个副本被传回时造成的。例如,如果我保存了一组订单,并且订单包含对客户的引用。2个订单引用了同一客户。当我将订单#1附加到客户#1时,客户1现在与上下文关联。当我尝试附加订单#2时,Customer#1的实例与订单#1的实例不同,因此附加订单#2将生成错误。处理分离实体时,需要采取步骤确保图形中引用同一记录的所有对象实例都使用相同的对象实例引用。当您从EF加载数据时,这些将是相同的对象引用,但是如果您将它们馈送到序列化器/反序列化器,您将得到两个相同的副本作为单独的引用。不能简单地重新附着这些对象引用
不幸的是,我无法提供一个简单的答案来简化操作,但这就是为什么序列化和反序列化实体可能是一个糟糕的想法,甚至分离/附加实例也可能是一件痛苦的事情。可能集合中只有一个项。该项很可能有主键,因此只能添加一次。@Bigabdoul否,我知道至少有两个项目,我已经调试过了it@jdweng每一项都有自己的主键,但可怕的是整个方法都失败了。在foreach之后有更多的代码(我没有在问题示例中包括),而且它正在被跳过。我看到过类似这样的问题。在花时间逐步浏览代码之后,我通常会发现一个异常。似乎c#在发现没有异常处理程序的异常时,它会向上移动执行堆栈,并在祖先方法中找到第一个异常处理程序。异常处理程序可以是祖先中的任何位置。因此,当我在异常之后单步执行代码时,它会转到父方法,然后疯狂地跳转到另一段代码中的异常处理程序。要修复此问题,我添加了一个新的异常处理程序。正如您所说,更改
List.ForEach()
会引发导致问题的异常。但是我不知道为什么会抛出它,如果我在调用Context.SaveChanges()
时没有附加它,我会收到另一个异常,说有一些元素不在上下文中,但是如果我添加了附加元素,另一个例外是,元素已经在上下文中。这可能是附加引用和未附加引用的组合。如果对象A引用了B的实例,而每个B引用了C的实例,则需要根据上下文检查链中的每个实例。附加和分离对象图是一件非常麻烦的事情。我已经扩展了答案,以涵盖附加实体时需要注意的一些事情。谢谢!显然这就是问题所在,我有