3

我首先在以下模型中使用 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未更改。

ActionSave不知道属性更改是什么,它只需要Record正确更新并创建丢失或更新现有的子模型,也有可能某些Child类也可能有自己的嵌套更改,所以我需要一个方法,以某种方式通过模型递归比较新模型与现有模型,并将应用适当的更改。那么我该怎么做呢?

4

1 回答 1

0

我最终将我的每个模型和 ViewModel 类与EntityState属性连接起来,所以现在当我更改一些属性时,我将其设置EntityStatechanged状态,当我创建一个属性时,我将属性设置为 state Added,最初模型是用Unchanged状态初始化的,基本上它看起来像下面这样:

[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
}

然后在服务器上我执行以下操作

    [HttpPost, HttpGet]
    public HttpResponseMessage SaveRecord(RecordViewModel record)
    {
        var model = Mapper.Map<Record>(record);

        if (!ModelState.IsValid)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }

        db.Attach(model);

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
        }

        return Request.CreateResponse(HttpStatusCode.OK);
    }

这是 Attach 方法的实现:

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

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;
            }
        }
    }
于 2013-06-23T11:32:15.067 回答