Entity framework 实体框架条目更改跟踪问题
我有下面列出的配置文件模型。该模型通过ajax调用发送到客户端,然后通过另一个ajax调用进行更新并发送回服务器 当客户机进行更改时,他们负责设置正在使用的模型的ObjectState。例如,如果要更改Name属性,则会将Name属性设置为新值,并将ObjectState属性设置为2(已修改),如果要向地址添加新地址,则会将新地址的ObjectState设置为1(已添加)。这一切都非常有效,ApicController正确地接收新的概要文件对象Entity framework 实体框架条目更改跟踪问题,entity-framework,Entity Framework,我有下面列出的配置文件模型。该模型通过ajax调用发送到客户端,然后通过另一个ajax调用进行更新并发送回服务器 当客户机进行更改时,他们负责设置正在使用的模型的ObjectState。例如,如果要更改Name属性,则会将Name属性设置为新值,并将ObjectState属性设置为2(已修改),如果要向地址添加新地址,则会将新地址的ObjectState设置为1(已添加)。这一切都非常有效,ApicController正确地接收新的概要文件对象 public enum ObjectState {
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; }
}
公共枚举对象状态
{
未更改=0,
添加=1,
修改=2,
删除=3
}
公共接口IObjectState
{
ObjectState对象状态{get;set;}
}
静态类EntityStateHelper
{
公共静态EntityState ConvertState(ObjectState ObjectState)
{
开关(对象状态)
{
案例ObjectState。添加:
返回EntityState。已添加;
案例ObjectState。已删除:
返回EntityState。已删除;
案例ObjectState.Modified:
返回EntityState.Modified;
违约:
返回EntityState。未更改;
}
}
}
//模型
公共类配置文件:IObjectState
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共日期时间?生日{get;set;}
//导航属性
公开收集
如果能帮我指出正确的方向,我将不胜感激。我建议在更新方法中使用.Add(entity)添加实体这会将新地址标记为已添加,并修复其导航属性。然后,当您调用ApplyStateChanges时,它会更正状态。这篇文章很旧,但它可能会帮助其他人:
问题在于更新方法。我假设您正在断开连接的模式下工作。
以下方法:
_context.Entry<T>(entity);
这意味着您不关心以前应用的状态,只要它们被跟踪(而不是处于分离状态)
我非常确定代码_context.Entry(entity)应该是_context.Entry(entity.State=EntityState.Modified,但是无论我做了什么尝试,我似乎都无法绕过这个异常
如果在之后不执行ApplyStateChanges(),则它会更新实体及其整个图形,并将其标记为脏,从而产生意外的结果(当然就像添加其图形元素一样。请检查整个说明)
ObjectStateManager中已存在具有相同键的对象。ObjectStateManager无法跟踪具有相同键的多个对象
这意味着您的数据库/测试中已经有相同的对象(或者更确切地说是它的一个导航属性)。
这与您的“真实”问题无关,更可能是一种副作用。请签入数据库的种子方法,您必须具有重复的导航实体
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);
}
}
}
_context.Entry<T>(entity);
_context.ApplyStateChanges();