【发布时间】:2012-10-26 17:01:05
【问题描述】:
我有下面列出的 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 对象的情况下,客户端没有删除配置文件的服务调用,所以他们对配置文件所能做的实际上就是修改它。在我的更新方法中,我选择使用_context.Entry<T>(entity) 与_context.Entry<T>(entity).State = EntityState.Modified 相对,因为这会引发异常,说明ObjectStateManager 中已经存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。
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 个地址。如果客户端将 Name 更改为 Steve 并修改 1 Address,那么当 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 视频 Entity Framework in the Enterprise 中获得了这个状态变化跟踪代码。
任何帮助我指出正确的方向将不胜感激。
【问题讨论】:
标签: entity-framework