我正在使用Entity Framework 6,我正在编写Save
方法来更新现有“案例”的详细信息,如下所示:
public void Save(User user, Case @case)
{
if (@case.Id == 0)
{
// deal with new case scenario
}
else
{
var existing = GetCase(@case.Id);
// update existing's properties with those in @case
context.Entity(existing).State = EntityState.Modified;
context.Entry(existing.SubEntity1).CurrentValues.SetValues(@case.SubEntity1);
context.Entry(existing.SubEntity2).CurrentValues.SetValues(@case.SubEntity2);
}
context.SaveChanges();
}
Case
类型具有RaisedBy
类型的User
属性,该属性派生自ASP.NET Identity IdentityUser
。
进行GetCase
调用后,我使用IQueryable.Include
同时加载附加到RaisedBy
媒体资源的用户。它似乎加载了User
作为代理,一个监视,而调试显示类型为System.Data.Entity.DynamicProxies.User_
后跟一个看起来像哈希的非常长的值。
当调用context.SaveChanges()
时,EF似乎尝试将用户重新写入表格,从而生成带有消息的DbUpdateException
:
违反PRIMARY KEY约束'PK_dbo.IdentityUsers'。无法在对象'dbo.IdentityUsers'中插入重复键。重复键值为(0799b4c2-a38e-430c-8031-1c27878f2f43)。 声明已经终止。
据我所知,RaisedBy
用户与从上下文加载的用户完全相同,所以我很难看到问题是如何悄然进入的。
答案 0 :(得分:0)
鉴于我在问题中省略的代码,在评论后面
// update existing's properties with those in @case
没有人能回答我并不感到惊讶。
问题在于,在那个省略的代码块中:
existing.Events.Add(new Event
{
CaseId = @case.Id,
Author = user,
Text = existing.GetChangeDescription(@case),
DateTime = now,
EventType = EventType.Update
});
我正在建立与User对象的关联,Entity Framework随后将其状态设置为添加,这是公平的,因为在此阶段没有在此上下文中加载此用户的跟踪,即使有,我会得到一个不同的“无法跟踪具有相同键的相同类型的对象”错误。最好的方法是:
我选择了1,因为它最适合我目前的架构,但是我正在考虑重构以使选项3成为可能。