2015-09-05 56 views
1

我有一個模型,我們可以稱之爲人爲什麼沒有我不能修改我的模型:具有相同鍵的對象已存在異常

// My table tb_person 
public class Person 
{ 
    public int Id {get;set;} 
    public string Name {get; set;} 
    public int Age {get; set;} 
    public DateTime AddTime {get; set;} 
    public DateTime UPdateTime {get;set;} 
    public string Remark {get; set} 
    public bool IsEnable {get;set;} 
} 

首先我得到的Mdoel

using (var ctx = new MyEntitys()) 
{ 
    ctx.Configuration.ProxyCreationEnabled = false; 
    ctx.Configuration.LazyLoadingEnabled = false; 

    Person firstModel = ctx.Persons.Where(x=> x.Id = 5).FirstOrDefault(); 
} 

現在很長一段時間我需要修改模型後,但我需要在數據庫中獲取舊模型並進行比較。

using (var ctx = new MyEntitys()) 
{ 
    ctx.Configuration.ProxyCreationEnabled = false; 
    ctx.Configuration.LazyLoadingEnabled = false; 

    Person CurrentModel = ctx.Persons.Where(x=> x.Id = 5).FirstOrDefault(); 
    // Just a example for judge or compare 
    if (CurrentModel.IsEnable) 
    { 
     if (CurrentModel.UpdateTime != null) 
     { 
     firstModel.Update = time; 
     } 
    } 
    else 
    { 
     firstModel.AddTime = new DateTime(); 
    } 
    ctx.Entry(firstModel).State = System.Data.Entity.EntityState.Modified; 
    ctx.SaveChanges(); 
} 

那麼它會拋出:

我爲什麼不使用CurrentModel更新?因爲firstModel我改變這麼多財產,我不想複製所有財產。我只需要從數據庫中獲取一些信息,然後替換它然後保存。


我已經看到這一點:An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

這樣,我不喜歡它。我感到困惑,而且很複雜。

我還用想另一種方式來固定它:

//只是判斷它沒有得到它

if (ctx.Persons.Any(x=> x.Id = 5 && x.UpdateTime != null){ 
    // then do something change after judge 
} 

Basicly現在我知道問題的根源是:實體框架緩存後的結果得到它 。這就是爲什麼我得到一個新的模型後,它不會讓我使用舊的。

但我仍然在尋找一種更好和更高的性能方式(我只想減少與數據庫的交易)來修復它。 你有什麼想法嗎?

回答

1

當您使用Entry()獲取對象的條目時,上下文將檢查上下文中是否存在該對象引用的條目,然後返回該條目,如果該對象引用沒有條目,則會爲該對象添加條目反對上下文。

當您創建var p1= new Person()var p2=new Person()時,則p1和p2不相同,即使它們的所有屬性都相同,它們也具有不同的引用。

在您的情況下,修改的實體(第一個)和原始實體是不同的實例,因此上下文嘗試爲第一個創建條目,並且因爲您已將原始版本加載到上下文中,將引發Object with the same key already exists的異常。

要知道你能做什麼,考慮一下這個場景:

方案1

在這種情況下,你從上下文中的人,並把它傳遞給客戶,然後客戶端將修改後的版本你把數據庫,並且你想檢查一些東西的原始版本,然後更新數據庫。 你應該做的是這樣的:

//get original version 
original= context.Persons.Where(x=> x.Id = modified.Id).FirstOrDefault(); 
//do comparison and what you want to do 
//but only apply changes to modified version 
if (original.Age > 20) 
    modified.SomeProperty=SomeValue; 

//save modified version 
context.Entry(original).CurrentValues.SetValues(modified); 
context.SaveChanges(); 

這種方式是想在Entity Framework

方案2

的早期版本在這種情況下ObjectContextApplyCurrentValues方法,你從一個人上下文並將其傳遞給客戶端,然後客戶端將修改後的版本發送給您,而您(無需檢查原始版本)將其放入數據庫中。

你應該做的是這樣的:

context.Entry(modified).State = EntityState.Modified; 
context.SaveChanges(); 

而且也沒有必要找到原件。

更多信息:

+0

對不起,我還是不明白。語言如此官方。你能用一些簡單的方法或代碼解釋它嗎?謝謝。 – qakmak

+0

是的,但強烈建議閱讀我輸入的有用鏈接Asnwer的更多信息部分:) –

+0

真的很抱歉,我已經看到它了。我不知道什麼是被跟蹤的實體。我也看不到代碼與我的代碼示例有任何關係..... – qakmak

相關問題