築巢

2013-06-22 99 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; 
      } 
     } 
    }