7

几个月来,我一直在研究我的 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 类进行保存时,它本身被认为是分离的。作为这个问题的解决方法,我对这篇博文和这个 SO question中发现的问题应用了类似的解决方案。考虑到在名为 MainClient 的对象中传递了 Edit 方法,下面是重新附加对象的代码之后的样子(我知道很乱)client

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 中使使用该代码提交到数据库如此不稳定?

有谁知道为什么会发生这种情况?

4

1 回答 1

0

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

于 2012-12-26T15:37:27.643 回答