【问题标题】:Entity Framework 4.3 vs. 5.0 Updating DifferencesEntity Framework 4.3 与 5.0 更新差异
【发布时间】:2012-12-08 08:46:09
【问题描述】:

几个月来我一直在研究我的 ASP.NET MVC 应用程序。当我第一次开始研究它时,我使用的是 Entity Framework 4.3 (Code-First w/Migrations)。当我这样做时,我在尝试对 MainClient 表进行更新时遇到了一些问题。 MainClient 包含客户的所有基本信息,并且与 BPClient 表具有 1:1 的关系,该表包含有关该客户的更多具体信息,与他们的 BP 模块许可协议有关。两者都可以在选项卡控件的同一页面上进行编辑。但是,在尝试将 MainClient 对象的 EntityState 更改为 EntityState.Modified 时,我不断收到以下异常:

System.InvalidOperationException : An object with the same key already exists 
in the ObjectStateManager. The ObjectStateManager cannot track multiple objects 
with the same key.

我在调试时注意到,当对象进入我的 Controller 类进行保存时,它本身被认为是分离的。作为此问题的解决方法,我对this blog postthis SO question 中发现的问题应用了类似的解决方案。下面是重新附加对象的代码之后的样子(我知道很乱),因为 Edit 方法在名为 client 的 MainClient 对象中传递:

var newClientObject = new MainClient { ClientID = client.ClientID };
Db.MainClients.Attach(newClientObject);
Db.Entry(newClientObject).CurrentValues.SetValues(client);

var bpClient = new BPClient { ClientID = client.ClientID, BaseClient = newClientObject };
if (client.BPClient != null)
{
    Db.BostonpostClients.Attach(bpClient);
    Db.Entry(bpClient).CurrentValues.SetValues(client.BPClient);
}

Db.SaveChanges()

这在所有测试用例中都工作得很好而且很花哨。直到最近。

最近,我升级了我的应用程序以使用 Entity Framework 5(仍然使用 Code-First)。但是,当我再次测试 MainClient 编辑页面时,我发现了一些相当不稳定的行为。某些字段在编辑时可以毫无问题地保存。其他人永远不会致力于数据库。还有一些会很好,但前提是它们是被编辑对象的唯一部分。我调试了 Controller 类中的 DbContext ,发现,相当烦人的是,不仅页面上所做的更改被发送到 Controller 类,而且 ObjectStateManager 中同时包含 MainClient 和 BPClient 对象它也包含在页面上所做的更改!我应该在这里提一下,顺便说一下,我在调试它时没有收到一个错误,即使在 SaveChanges() 之后也没有。

我决定尝试将代码还原为原来的样子,也就是说这样做的逻辑方式:

Db.Entry<BPClient>(client.BPClient).State = EntityState.Modified;
Db.Entry<MainClient>(client).State = EntityState.Modified;

Db.SaveChanges();

现在它工作得很好。没有 InvalidOperationException。这样就很好解决了。

仍然困扰着我的是试图弄清楚 5.0 中的哪些变化使我之前的修复停止工作并且对我一无所知。为什么该代码在 4.3 中可以正常工作,但在 5.0 中却不行?是什么在 5.0 中使使用该代码提交到数据库如此不稳定?

有人知道为什么会这样吗?

【问题讨论】:

标签: .net entity-framework entity-framework-4 entity-framework-5


【解决方案1】:

我自己也遇到过这个问题。我正在使用 IDbSet 类来填充数据库表,我发现当我使属性虚拟 EF5 执行延迟加载(我的虚拟属性在数据库中的其他对象处)时。这意味着我收到了虚拟财产的新主键。好吧,如果我没有与我想引用的对象关联的特定 ID,EF 5 会尝试建立双向关系。如果您没有明确告诉 EF 在 DBContext 中映射到哪个属性,它会为同一个对象设置两个外键,这是不允许的。希望这会有所帮助。

【讨论】:

  • 感谢您尝试回答我的问题。不过,我认为情况并非如此。我已经将 MainClient 和 BPClient 之间的 1:1 设置为双向关系(都具有虚拟属性和 ID)。我只是想弄清楚为什么代码突然停止工作。
  • 仅使用虚拟属性会导致延迟加载,您是否在属性之间的 dbcontext 中完成了相同的映射?
  • 我使用的是数据注释,而不是 Fluent API。映射完全在对象本身上,而不是在 DbContext 中。在 4.3 和 5.0 之间是否发生过延迟加载会以这种方式影响代码的事情?
  • 在我刚刚完成的一个应用程序上,我们从 4.3 更改为 5.0,如上所述,如果您尝试延迟加载和映射,那么您将获得两个键。我们修复它的方法是在 dbcontext 中直接映射一个 int fooId 和一个 int barId 属性,并且我们没有执行任何延迟加载,因为 EF 尝试执行多个,并且在某些情况下它无法选择哪一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多