你更新...
var f = db.Foos.First(x => someEqualityTest(foo));
f = foo;
...將無法正常工作,因爲你沒有改變加載和連接對象f
可言,你只是覆蓋變量f
與分離對象foo
。附加的對象仍然在上下文中,但是在加載後它沒有被改變,並且你沒有指向它的變量。 SaveChanges
在這種情況下不會做任何事情。
「標準選項」你們是:
var f = db.Foos.First(x => someEqualityTest(foo));
db.Entry(f).State = EntityState.Modified;
或只是
db.Entry(foo).State = EntityState.Modified;
// attaches as Modified, no need to load f
這標誌着作爲修改的所有特性 - 如果他們真的改變與否沒有關係 - 並且將發送更新爲數據庫的每一列。
這隻會標誌着真正改變屬性修改,並只發送了更改的列的UPDATE第二個選項:
var f = db.Foos.First(x => someEqualityTest(foo));
db.Entry(f).CurrentValues.SetValues(foo);
現在,200萬點要更新的對象,你沒有一個「標準「的情況,並且可能的是,兩種選擇 - 特別是可能使用內部反射來匹配源和目標對象的屬性名稱的第二種 - 太慢。
當涉及到更新性能時,最好的選擇是更改跟蹤代理。這意味着您需要將實體類中的EVERY屬性標記爲virtual
(不僅是導航屬性,還包括標量屬性),並且您不禁止創建更改跟蹤代理(默認情況下啓用)。
當您從數據庫加載對象f
時,EF將創建一個動態代理對象(從您的實體派生),類似於延遲加載代理,它將代碼注入到每個屬性設置器中以維護標誌,被改變或沒有。
代理提供的更改跟蹤比基於快照的更改跟蹤(發生在SaveChanges
或DetectChanges
)快得多。
我不確定,如果您使用更改跟蹤代理,上述兩個選項更快。這可能是你需要手動屬性分配,以獲得最佳性能:
var f = db.Foos.First(x => someEqualityTest(foo));
f.Property1 = foo.Property1;
f.Property2 = foo.Property2;
// ...
f.PropertyN = foo.PropertyN;
在我類似的更新情況經驗對象的幾千元也沒有改變對性能跟蹤代理真正的替代品。
你能擺脫你如何檢查多一點光,如果兩個實例Foo是平等的嗎?這是一個簡單的ID比較? – 2012-03-28 17:43:54
可能是,我只是想概括一下具體細節,並將注意力放在解決方案的較大邏輯方面 – Didaxis 2012-03-28 18:33:47