筑巢

2013-06-22 56 views
3

我使用EF代码首先用下面的模型实体框架AddOrUpdateOrDontBother:筑巢

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不知道的性能变化是什么,它只是需要正确更新Record和创建丢失或更新现有的子模型,它也有可能是一些Child类也可以有自己的嵌套的变化,因此我需要一种方法,通过模型比较新模型与现有模型进行比较,并将应用适当的更改。那我该怎么做?

+1

+1:

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具有下列实现。在EF中提交对象图是(仍然)乏味的工作。在Lerman&Miller的书_DbContext_中,提出了一种使用手动编码的自我跟踪实体(各种)的方法。不是银色的子弹,但伊莫。 –

+1

它可能是有用的: http://stackoverflow.com/questions/15336248/entity-framework-5-updating-a-record –

回答

0

我已经结束了与EntityState财产拼接每个我的模型和视图模型类的,所以现在当我改变了一些属性我设置EntityStatechanged状态,当我创建一个我设置的属性陈述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); 
    } 

这里是连接方法实现:方法名称

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