2011-05-06 40 views
25

我們有我們的代碼的通用更新方法,做了什麼原因.Attach()在EF4中速度慢?

foreach (var entity in entityList) 
{ 
    Context.GetIDbSet<T>().Attach(entity); 
    Context.SetState(entity, EntityState.Modified); 
} 

我通過傳遞實體的枚舉,每個實體調用這個曾經測試了這一點。

我在找的是1000個實體的枚舉大約需要47s才能運行。 這是預期的行爲?或者代碼片段有問題嗎?

分析顯示Attach()方法比SetState()方法慢。

我運行它的測試是一個具有50個屬性的實體,如果有任何影響,則不存在關係。

回答

66

我可以證實這種緩慢的行爲,我也發現了主要原因。我做了以下模型一個小測試...

public class MyClass 
{ 
    public int Id { get; set; } 
    public string P1 { get; set; } 
    // ... properties P2 to P49, all of type string 
    public string P50 { get; set; } 
} 

public class MyContext : DbContext 
{ 
    public DbSet<MyClass> MyClassSet { get; set; } 
} 

...這測試程序...

using (var context = new MyContext()) 
{ 
    var list = new List<MyClass>(); 
    for (int i = 0; i < 1000; i++) 
    { 
     var m = new MyClass() 
     { 
      Id = i+1, 
      P1 = "Some text ....................................", 
      // ... initialize P2 to P49, all with the same text 
      P50 = "Some text ...................................." 
     } 
     list.Add(m); 
    } 

    Stopwatch watch = new Stopwatch(); 
    watch.Start(); 
    foreach (var entity in list) 
    { 
     context.Set<MyClass>().Attach(entity); 
     context.Entry(entity).State = System.Data.EntityState.Modified; 
    } 
    watch.Stop(); 
    long time = watch.ElapsedMilliseconds; 
} 

測試1

沒錯上面的代碼:

- >時間= 29.2秒


試驗2

註釋掉線...

//context.Entry(entity).State = System.Data.EntityState.Modified; 

- >時間= 15.3秒


測試3

註釋掉該行...

//context.Set<MyClass>().Attach(entity); 

- >時間= 57.3秒

這個結果很奇怪,因爲我預計調用Attach是沒有必要的,因爲改變無論如何,國家都會重視。


試驗4

刪除屬性P6至P50(所以我們只有在實體5串),原來的代碼:

- >時間= 3,4秒

所以,很顯然,屬性的數量非常重要。


試驗5

(與所有50個屬性再次模型)添加循環之前以下行:

context.Configuration.AutoDetectChangesEnabled = false; 

- >時間= 1,4秒


試驗6

再次用AutoDetectChangesEnabled = false但只有5個屬性:

- >時間= 1,3秒

所以,不改變跟蹤屬性的數目並不重要所以多了。


結論

通過大部分的時間遠遠似乎花費由更改跟蹤機制採取附加對象屬性的快照。如果您不需要它,請禁用您的代碼段的更改跟蹤。 (我想在你的代碼你真的不需要改變由entitiy的狀態設置爲Modified跟蹤,因爲你基本上標記所有屬性,無論如何改變,所以所有列被髮送到一個更新語句的數據庫。)

編輯

上面的測試時間是在調試模式下。但釋放模式沒有太大的區別(例如:測試1 = 28.7秒,測試5 = 0.9秒)。

+2

+1這是非常棒的解釋,因爲快照更改跟蹤被認爲非常慢,但我認爲慢操作實際上是評估更改,但是看起來創建快照也很慢。 EF的另一個問題。 – 2011-05-07 13:51:13

+0

這是一個非常棒的答案...我曾想過更改跟蹤,但不知道有辦法關閉它...我今天晚些時候會試試這個......謝謝 – taylonr 2011-05-07 14:23:46

+0

這樣做。非常感謝。這個錯誤昨天下午4點左右引起了我的注意,這讓我很擔心我的夜晚想到這件事。就像我說的,我在跟蹤思考,但沒有考慮上下文設置,並且可能沒有到達那裏。 – taylonr 2011-05-07 15:47:07

相關問題