【问题标题】:Modify and/or delete records under one transaction修改和/或删除一笔交易下的记录
【发布时间】:2016-09-14 21:51:13
【问题描述】:

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

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

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

附加“ItemObject”类型的实体失败,因为另一个实体 相同类型的已经有相同的主键值...

调用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 的概念,所以我想不出解决这个错误并仍然满足作业要求的方法。

【问题讨论】:

  • SaveChanges 应该为您处理所有事务
  • @SamIam 我不知道,但我知道我仍然收到错误
  • 错误是 io 中的某些条目确实具有相同的 Id(或该对象的任何 PK 名称)值。要么您添加了两次相同的项目,要么您的 id 值未正确初始化。由于 Entry() 方法将对象附加到上下文,因此这些行中的任何一行都可能导致此异常。如果所有条目都具有正确的 id 值,则 SaveChanges() 调用将在单个事务中保留上下文中的更改(或 changetracker,因为它还将跟踪所有相关条目)。

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


【解决方案1】:

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

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

请参阅此url 中的“无跟踪查询”

【讨论】:

  • 我的问题是我误解了要求...我不应该更改序列号,因为它是主键的一部分...当我想到它时这是非常自然的然后。现在这工作正常,但逻辑完全不同
【解决方案2】:

您可以通过针对您的上下文分析 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。 调试和修复与上下文相关的问题的简单方法。 让我知道这是否有帮助!

【讨论】:

  • 它没有到达特定的代码行。它在ctx.Entry(i).State = EntityState.Modified; 崩溃
猜你喜欢
  • 1970-01-01
  • 2014-11-19
  • 2019-07-16
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-04
  • 2022-11-02
相关资源
最近更新 更多