C# 实体框架AddorUpdateOrdOnToWn与嵌套

C# 实体框架AddorUpdateOrdOnToWn与嵌套,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我首先将EF代码用于以下模型: public class Root { public ChildA A { get; set; } public ChildB B { get; set; } public ChildC C { get; set; } } 假设你有一个控制器 public class RecordController { ... public void Save(Root root) { ... }

我首先将EF代码用于以下模型:

public class Root
{
    public ChildA A { get; set; }
    public ChildB B { get; set; }
    public ChildC C { get; set; }
}
假设你有一个控制器

public class RecordController 
{
    ...

    public void Save(Root root)
    {
        ...
    }

    ...
}
并且您的
Root
控制器已从客户端接收到一个模型,该模型包含以下更改:属性
a
是全新的,尚未添加到数据库中,需要创建;属性
B
已存在于数据库中,需要更新;属性
C
未更改


操作
Save
不知道属性更改是什么,它只需要正确更新
记录
,并创建缺少的或更新现有的子模型,也可能一些
子类也有自己的嵌套更改,因此,我需要一个方法,该方法将以某种方式通过模型递归,将新模型与现有模型进行比较,并应用适当的更改。那么我该怎么做呢?

我最终将我的每个模型和ViewModel类与
EntityState
属性连接起来,所以现在当我更改某些属性时,我将
EntityState
设置为
changed
状态,当我创建一个属性时,我将属性设置为state
Added
,最初,模型以
未更改的状态初始化,基本上如下所示:

[Table("City")]
[KnownType(typeof(Country))]
public class City
{
    public City()
    {
        Airports = new List<Airport>();
        LastUpdate = DateTime.Now;
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Int32 Id { get; set; }

    public Int32? CountryId { get; set; }

    [StringLength(50)]
    public String Name { get; set; }

    [Range(-12, 13)]
    public Int32? TimeZone { get; set; }

    public Boolean? SummerTime { get; set; }
    public DateTime? LastUpdate { get; set; }

    [ForeignKey("CountryId")]
    public virtual Country Country { get; set; }

    [NotMapped]
    public EntityState? EntityState { get; set; } // <----------- Here it is
}
AttachAndMarkAs具有以下实现:

    public void AttachAndMarkAs<T>(T entity, EntityState state, Func<T, object> id) where T : class
    {
        var entry = Entry(entity);

        if (entry.State == EntityState.Detached)
        {
            var set = Set<T>();

            T attachedEntity = set.Find(id(entity));

            if (attachedEntity != null)
            {
                var attachedEntry = Entry(attachedEntity);

                attachedEntry.CurrentValues.SetValues(entity);
            }
            else
            {
                entry.State = state;
            }
        }
    }
public void AttachAndMarkAs(T entity,EntityState,Func id),其中T:class
{
var分录=分录(实体);
if(entry.State==EntityState.Detached)
{
var set=set();
T attachedEntity=set.Find(id(实体));
如果(附件身份!=null)
{
var attachedEntry=条目(attachedEntity);
attachedEntry.CurrentValues.SetValues(实体);
}
其他的
{
entry.State=状态;
}
}
}

+1表示方法名称。在EF中提交对象图(仍然)是一项乏味的工作。在Lerman&Miller的书DbContext中,提出了一种使用手动编码的自跟踪实体(种类)的方法。目前还不是银弹。它可能很有用:
    public void Attach(City entity)
    {
        if (entity != null)
        {
            Attach(entity.Country);

            AttachAndMarkAs(entity, entity.EntityState ?? EntityState.Added, instance => instance.Id);
        }
    }
    public void Attach(Country entity)
    {
        if (entity != null)
        {
            AttachAndMarkAs(entity, entity.EntityState ?? EntityState.Added, instance => instance.Id);
        }
    }
    public void AttachAndMarkAs<T>(T entity, EntityState state, Func<T, object> id) where T : class
    {
        var entry = Entry(entity);

        if (entry.State == EntityState.Detached)
        {
            var set = Set<T>();

            T attachedEntity = set.Find(id(entity));

            if (attachedEntity != null)
            {
                var attachedEntry = Entry(attachedEntity);

                attachedEntry.CurrentValues.SetValues(entity);
            }
            else
            {
                entry.State = state;
            }
        }
    }