我寫了一個簡單的導入/導出應用程序,它使用EntityFramework和AutoMapper轉換源 - >目標中的數據。它基本上是:Entityframework DbContext的泛型導致性能下降?
- 選擇
batchSize
從 - 「地圖」數據源 - >目標實體
- 從源表中的記錄添加新的目的地實體目標表和節省背景
我移動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();
}
}
爲什麼在while塊的每次迭代中創建一個新的目標實例?你可以在while語句之外移動它。 – rcdmk
簡介該應用程序,並確切知道!如果您手邊沒有任何分析器,請暫停調試器10次。 – usr
您可以在評論中提問,可以通過時間跟蹤(StopWatch)輕鬆驗證問題。 –