2013-06-24 260 views
2

編輯

我錄了一段截屏與我的問題,你可以找到它here,請看,如果你有時間。實體框架創建重複實體

我有下面的代碼應該執行AddOrUpdate功能,而是所有現有的記錄被重新創建,因此我有幾個紐約,幾個美國的。我從客戶端傳輸EntityState,以便如果客戶端上的數據發生更改,客戶端會相應地更新EntityState屬性並將其發送到服務器。

[HttpPost, HttpGet, HttpPut] 
    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, Mapper.Map<RecordViewModel>(model)); 
    } 

我附加實體具有以下功能

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

       if (state != EntityState.Unchanged) 
       { 
        attachedEntry.CurrentValues.SetValues(entity); 
        attachedEntry.State = state; 
       } 
      } 
      else 
      { 
       entry.State = state; 
      } 
     } 
    } 

這是通過以下的人轉述:

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

我不明白這部分的代碼添加手柄實體而不是更新它們,因爲EntityState值是正確的...

+1

如果你說「我不知道哪一部分呢?」不那意味着你從別處複製了代碼? –

+0

您的EntityState爲空,因此它始終將其視爲Add。 – Maess

+0

您是否設置了一些斷點並查看發生了什麼? – MaxSC

回答

3

如果喲你正在使用簡單的int作爲你的id,你可以使用下面的方法。

public abstract class BaseEntity 
{ 
    public int Id { get; set; } 
} 

public void AddOrUpdate<T> (T entity) where T : BaseEntity 
{ 
    if(entity.Id > 0){ 
     Entry(entity).State = EntityState.Modified; 
    } 
    else 
    { 
     Set<T>().Add(entity); 
    } 
} 

// 

var model = Mapper.Map<Record>(record); 
db.AddOrUpdate(model); 
db.SaveChanges(); 
+0

嗯,讓我試試... – Lu4

+0

真的很奇怪,問題依然存在... – Lu4

+0

我想我已經得到它,我有外部的實體,其中包含兒童的實體。子項目是創建的「獨立」屬性 – Lu4

2

你需要注意的實體框架是如何處理孩子/引用的實體,當你編程更改父實體的狀態。

看看這個article,它總結了事情在許多不同情況下的工作方式。

在下面的例子中,你可能會認爲,所有被引用的實體將被自動設置爲Modifiied

using (var context = new BloggingContext()) 
{ 
    context.Entry(existingBlog).State = EntityState.Modified; 
    // Do some more work... 
    context.SaveChanges(); 
} 

但實際上,他們不會。 書面上的文章:

如果您有需要註明修改時間,你應該 單獨設置的狀態這些實體的多個實體。

最後,這裏是你需要處理AddOrUpdate具體情況的方式,當你PrimaryKeyInt

using (var context = new BloggingContext()) 
{ 
    context.Entry(blog).State = blog.BlogId == 0 ? EntityState.Added : EntityState.Modified; 

    context.SaveChanges(); 
} 
+0

您的示例如何顯示引用的實體保持不變的狀態? –

+0

對不起,我不清楚,我已經更新了我的答案。我從[那裏](http://msdn.microsoft.com/en-us/data/jj592676.aspx)舉了一個例子,告知開發人員有關「EntityState」修改的真實行爲。 – MaxSC

+0

感謝您的鏈接,真的很有幫助 – Lu4