我有下面列出的 Profile 模型。此模型通过 ajax 调用发送到客户端,然后通过另一个 ajax 调用更新并发送回服务器。
当客户端进行更改时,他们负责设置他们正在使用的模型的 ObjectState。例如,如果他们正在更改 Name 属性,他们会将 Name 属性设置为新值,并将 ObjectState 属性设置为 2(已修改),并向地址添加新地址,他们会将新地址的 ObjectState 设置为 1 (添加)。这一切都很好, ApiController 正确接收新的 Profile 对象。
public enum ObjectState
{
Unchanged = 0,
Added = 1,
Modified = 2,
Deleted = 3
}
public interface IObjectState
{
ObjectState ObjectState { get; set; }
}
static class EntityStateHelper
{
public static EntityState ConvertState(ObjectState objectState)
{
switch (objectState)
{
case ObjectState.Added:
return EntityState.Added;
case ObjectState.Deleted:
return EntityState.Deleted;
case ObjectState.Modified:
return EntityState.Modified;
default:
return EntityState.Unchanged;
}
}
}
// Models
public class Profile : IObjectState
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? BirthDay { get; set; }
// Navigation Properties
public ICollection<Address> Addresses { get; set; }
public ObjectState ObjectState { get; set; }
}
public class Address : IObjectState
{
public int Id { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public ObjectState ObjectState { get; set; }
}
在我的 ProfileRepository 内部,我实际上已经分离了 Insert 和 Update,对于 Profile 对象,客户端没有删除配置文件的服务调用,所以他们对配置文件所能做的就是修改它。在我的 Update 方法中,我选择使用_context.Entry<T>(entity)
asapposed_context.Entry<T>(entity).State = EntityState.Modified
导致抛出异常,指出ObjectStateManager 中已经存在具有相同键的对象。ObjectStateManager 无法使用相同的 key 跟踪多个对象。
public void Update(T entity)
{
_context.Entry<T>(entity);
_context.ApplyStateChanges();
}
首先让我说我在 Update 方法中实际上没有 ApplyStateChanges,但对于这个示例,它将显示正在发生的事情。下面是 ApplyStateChanges 方法的代码。
public static class DbContextEntensions
{
public static void ApplyStateChanges(this DbContext context)
{
foreach (var trackableEntry in context.ChangeTracker.Entries<IObjectState>())
{
IObjectState state = trackableEntry.Entity;
trackableEntry.State = EntityStateHelper.ConvertState(state.ObjectState);
}
}
}
所以这就是问题所在。假设客户端的 Profile 是 Name 属性是 John,Addresses 属性包含 1 个地址。如果客户端将名称更改为 Steve 并修改 1 地址,那么当 ApplyStateChanges 被调用时,每个 DbEntityEntries 都会被标记为正确的 EntityState。当客户端将新地址添加到状态为 1(已添加)的地址集合时,就会出现问题。当调用 ApplyStateChanges 时,context.ChangeTracker.Entries<IObjectState>()
对它的调用不会将新添加的地址作为已被 ChangeTracker 更改的条目返回。
我很确定代码_context.Entry<T>(entity)
应该是_context.Entry<T>(entity).State = EntityState.Modified
,但无论我尝试了什么,我似乎都无法解决这个异常。
我将 EntityFramework 5.0 与 .NET 4.0 一起使用,这意味着 EntityFramework 版本为 4.4。我错过了什么?我已经阅读了我能找到的关于这个主题的每一篇文章,这看起来应该有效。我从 Julie Lerman 的 PluralSight video Entity Framework in the Enterprise获得了这个状态变化跟踪代码。
任何帮助我指出正确的方向将不胜感激。