修改和/或删除一个事务下的记录

时间:2016-09-14 21:51:13

标签: c# entity-framework asp.net-mvc-5 primary-key

我知道有很多关于我得到的错误的问题,但在同一场景中没有一个问题。我需要在一个"事务"下更新和/或删除一个对象的几个项目。与实体框架。

我有一个项目对象列表,让我们称之为List<ItemObject>和可以拥有这些项目的对象 - 称之为SuperObject ItemObjects 有一个复杂的主键,由 SuperObject 的主键和该列表中的序列号组成。

场景:用户修改某些项目并将其他项目标记为删除。然后他点击一个按钮保存所有更改。对于我的任务,我需要模拟交易 - 这不是使用EF的好方法,我知道。所以,我需要在项目上设置状态,然后调用ctx.SaveChanges()。我的问题是,在更新序列号时,我得到多个匹配的主键值(我猜),这引起了臭名昭着的错误:

  

附加类型&#39; ItemObject&#39;的实体因为另一个实体而失败   相同类型的已经具有相同的主键值...

通过拨打ctx.Entry(i).State = EntityState.Modified;

时崩溃

有关如何解决此问题的任何想法?代码如下。

SuperObject objWithItems = (SuperObject)Session["Super"];
List<ItemObject> itemsToKeep = new List<ItemObject>();

foreach(ItemObject io in objWithItems.Items)
                {
                    if (io.Deletion)
                    {
                        ctx.Entry(io).State = EntityState.Deleted;
                    }
                     else
                        itemsToKeep.Add(io);  
                }

                int serial = 0;

                foreach(ItemObject i in itemsToKeep)
                {
                    i.Serial = ++serial;
                    ctx.Entry(i).State = EntityState.Modified;
                }

                ctx.SaveChanges();
            } 

                return RedirectToAction("Read", new { update = false });
        }

我非常喜欢这个,并且仍在掌握EF的概念,所以我无法找到绕过这个错误的方法并仍然满足作业的要求。

2 个答案:

答案 0 :(得分:1)

您可以通过分析上下文的ChangeTracker来调试问题。 在ctx.SaveChanges()之前添加以下代码并使用循环内的断点调试应用程序。

        var ctxEnteries = ctx.ChangeTracker.Entries();
        foreach (var entry in ctxEnteries)
        {
            //you can inspect the value like originalvalue, currentvalue, state, etc...
            var state = entry.State;
            var entity = entry.Entity;
        }

        ctx.SaveChanges();

因此,您可以准确找到导致问题的ItemObject。 轻松调试和修复与上下文相关的问题。 如果这有帮助,请告诉我!

答案 1 :(得分:1)

在这种情况下,您的上下文已经包含您的实体的条目,因此它不允许您添加同一实体的另一个条目。

您需要在查询中明确提及“.AsNoTracking()”。

请参阅此url

中的“无跟踪查询”