Entity framework 实体框架条目更改跟踪问题

Entity framework 实体框架条目更改跟踪问题,entity-framework,Entity Framework,我有下面列出的配置文件模型。该模型通过ajax调用发送到客户端,然后通过另一个ajax调用进行更新并发送回服务器 当客户机进行更改时,他们负责设置正在使用的模型的ObjectState。例如,如果要更改Name属性,则会将Name属性设置为新值,并将ObjectState属性设置为2(已修改),如果要向地址添加新地址,则会将新地址的ObjectState设置为1(已添加)。这一切都非常有效,ApicController正确地接收新的概要文件对象 public enum ObjectState {

我有下面列出的配置文件模型。该模型通过ajax调用发送到客户端,然后通过另一个ajax调用进行更新并发送回服务器

当客户机进行更改时,他们负责设置正在使用的模型的ObjectState。例如,如果要更改Name属性,则会将Name属性设置为新值,并将ObjectState属性设置为2(已修改),如果要向地址添加新地址,则会将新地址的ObjectState设置为1(已添加)。这一切都非常有效,ApicController正确地接收新的概要文件对象

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();