1

EntityFramework と AutoMapper を使用して、ソースから宛先へデータを変換する単純なインポート/エクスポート アプリケーションを作成しました。それは基本的に:

  1. batchSizeソース テーブルからのレコードの選択
  2. ' maps ' ソース -> 宛先エンティティからのデータ
  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 に答える