1

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

  1. batchSize从源表中选择记录
  2. 来自源->目标实体的“映射”数据
  3. 新的目标实体添加到目标表并保存上下文

我在 5 分钟内移动了大约50 万条记录。在我使用泛型重构代码后,性能在 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();
    }
}
4

1 回答 1

1

问题是调用Func您经常做的代表。将结果值缓存在变量中就可以了。

于 2012-11-07T14:08:28.060 回答