2012-11-07 28 views
1

我寫了一個簡單的導入/導出應用程序,它使用EntityFramework和AutoMapper轉換源 - >目標中的數據。它基本上是:Entityframework DbContext的泛型導致性能下降?

  1. 選擇batchSize
  2. 地圖」數據源 - >目標實體
  3. 從源表中的記錄添加新的目的地實體目標表和節省背景

我移動5分鐘內500k條記錄。在重構代碼使用泛型後,性能在5分鐘內急劇下降到250個記錄。

我的代表是否在DbContext上返回DbSet<T>屬性導致這些問題?或者還在發生其他事情?

快速非通用代碼:

public class Importer 
{   
    public void ImportAddress() 
    { 
     const int batchSize = 50; 
     int done = 0; 
     var src = new SourceDbContext(); 

     var count = src.Addresses.Count(); 

     while (done < count) 
     { 
      using (var dest = new DestinationDbContext()) 
      { 
       var list = src.Addresses.OrderBy(x => x.AddressId).Skip(done).Take(batchSize).ToList(); 
       list.ForEach(x => dest.Address.Add(Mapper.Map<Addresses, Address>(x))); 

       done += batchSize; 

       dest.SaveChanges(); 
      } 
     } 

     src.Dispose(); 
    } 
} 

(非常)慢的通用代碼:

public class Importer<TSourceContext, TDestinationContext> 
    where TSourceContext : DbContext 
    where TDestinationContext : DbContext 
{ 
    public void Import<TSourceEntity, TSourceOrder, TDestinationEntity>(Func<TSourceContext, DbSet<TSourceEntity>> getSourceSet, Func<TDestinationContext, DbSet<TDestinationEntity>> getDestinationSet, Func<TSourceEntity, TSourceOrder> getOrderBy) 
     where TSourceEntity : class 
     where TDestinationEntity : class 
    { 
     const int batchSize = 50; 
     int done = 0; 
     var ctx = Activator.CreateInstance<TSourceContext>(); 
     //Does this getSourceSet delegate cause problems perhaps? 

     //Added this 
     var set = getSourceSet(ctx); 

     var count = set.Count(); 

     while (done < count) 
     { 
      using (var dctx = Activator.CreateInstance<TDestinationContext>()) 
      { 
       var list = set.OrderBy(getOrderBy).Skip(done).Take(batchSize).ToList(); 
       //Or is the db-side paging mechanism broken by the getSourceSet delegate? 
       //Added this 
       var destSet = getDestinationSet(dctx); 
       list.ForEach(x => destSet.Add(Mapper.Map<TSourceEntity, TDestinationEntity>(x))); 

       done += batchSize; 
       dctx.SaveChanges(); 
      } 
     } 

     ctx.Dispose(); 
    } 
} 
+0

爲什麼在while塊的每次迭代中創建一個新的目標實例?你可以在while語句之外移動它。 – rcdmk

+0

簡介該應用程序,並確切知道!如果您手邊沒有任何分析器,請暫停調試器10次。 – usr

+0

您可以在評論中提問,可以通過時間跟蹤(StopWatch)輕鬆驗證問題。 –

回答

1

問題是Func代表你做了很多的調用。將結果值緩存在變量中,它會很好。

+0

我改變了通用代碼(參見//增加了這個)爲'Func <>'結果使用變量,但它仍然很慢...... – Ropstah

+0

它仍然在while循環中。 –

+0

正確,它需要在每個批處理後創建一個新的上下文,因爲緩存。否則,對象變成大的方式。 – Ropstah

相關問題