Entityframework DbContext周围的泛型导致性能下降?

时间:2012-11-07 13:06:53

标签: performance entity-framework generics dbcontext

我编写了一个简单的导入/导出应用程序,它使用EntityFramework和AutoMapper转换来自source->目标的数据。它基本上是:

  1. 从源表
  2. 中选择 batchSize条记录 来自source->目标实体的
  3. '地图'数据
  4. 将新目标实体添加到目标表并保存上下文
  5. 我在5分钟内移动 500k记录。在重构代码使用泛型之后,性能在5分钟内急剧下降到250条记录。

    我的代理人是否会在DbSet<T>上返回导致这些问题的DbContext属性?或者还有其他事情发生了吗?

    快速非通用代码:

    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();
        }
    }
    

1 个答案:

答案 0 :(得分:1)

问题是你正在做很多事情的Func代表的调用。将结果值缓存在变量中,它会没问题。