2017-07-19 2 views
0

最終データベース(D)にない特定のデータに別のデータベース(O)から移行する必要があります。問題の1つは、データベースのテーブルにフィールド内の異なる名前。私はとDのデータベースにないデータを取得してやろうとしました:Entity Frameworkで大きすぎるとパフォーマンスが悪い

var dtOrigin = from o in genEntitCeres.X.AsNoTracking() select o; 
var dtDestiny = from d in genEntitAgp.X.AsNoTracking() select d; 

var rowsMatch = from tOrigin in dtOrigin.AsEnumerable() 
        join tDestiny in dtDestiny.AsEnumerable() 
         on new { tOrigin.a, tOrigin.b} equals 
         new { tDestiny.a, tDestiny.b} 
        select tOrigin; 

var rowsNotMatch = (from tOrigin in dtOrigin.AsEnumerable() 
        where !rowsMatch.Contains(tOrigin) 
        select tOrigin); 

私は、各またはrowsNotMatch.Count()のために何しようとしたとき、それはあまりにも長い時間がかかる...

を私の解決策は、SqlQueryを使用して問合せからDismatch行を取得していました(データの不一致によりますが、5秒以下です)。しかし、私のコードのように、EFの別の方法があるかどうかを知りたいが、それは凍結していない。

答えて

1

これは、2つの異なるdbContextで2つのテーブルを開き、各テーブルの2つのカラムに基づいて2つのテーブルを比較し、一致しない元のテーブルのローを見つけようとしているようです。このようなことをEFを使って行うことは、私の推薦ではありません。これをdatabase/w tempテーブルで行う方がはるかに良いでしょう。各テーブルの.AsEnumerable()を実行することによって、これらのテーブルの内容全体をメモリにロードしています。

あなたはコードでこのような何かを行う必要がある場合:私は何かを検討したい:この先テーブルが大きいと予想されている場合は、あなたが1000のページでこれを実行する必要があり

var destinationMatches = genEntitAgp.X.AsNoTracking() 
    .Select(x=> new { x.id, x.a, x.b }) 
    .ToList(); 

をか.Skip()と.Take()を使用してください。

次のステップは、すべての行を起点DBのバッファテーブルに挿入することです。バッファテーブルには、宛先行のPKと照合する基準が格納されます。

public class TempX 
{ 
    public int Id { get; set; } 
    public string a { get; set; } 
    public string b { get; set; } 
} 

私は、このための別のDBContextではなく、起源1をお勧めします変更の追跡なしで初期化するために、そしてTempXテーブルに最初にすべてのレコードをクリア。 1,000を超える行を挿入する場合は、saveChanges 1000のバッチでこれを行い、各バッチでコンテキストを破棄して再作成し、操作を高速に保ちます。起源dbContextはTempXについても知っておく必要があります。

レコードはソーススキーマにtempX表にしたら:

var entities = genEntitCeres.X.AsNoTracking() 
    .Where(x => !genEntitCeres.TempX.AsNoTracking().Any(tx=>tx.a == x.a && tx.b == x.b)).ToList(); 

再び非マッチの多くは、その後のではなく.ToList(があることが予想される場合).SKIPを使用()と.Take()のアプローチです。

これは、特定のデータベースで複数回実行される可能性がある場合は、元のデータベースと宛先データベースの両方をフィルタリングするために使用できるCreatedAt/ModifiedAt dateTime値。私。最後の実行DateTimeを記録し、> LastRunDateに基づいて両方のクエリの行をフィルタリングして、引っ張って比較した行の数を減らします。

+0

ありがとうSteve Py! – kartGIS

1

はこのような何かを試してみてください:

var rowsNotMatch = from tOrigin in dtOrigin.AsEnumerable() 
        join tDestiny in dtDestiny.AsEnumerable() 
         on new { tOrigin.a, tOrigin.b} equals 
         new { tDestiny.a, tDestiny.b} into gD 
        from d in gD.DefaultIfEmpty() 
        where d == null 
        select tOrigin 

これは本質的に、左がdtDestinyで一致していないdtOriginで項目のみを返し、dtOriginとdtDestiny間の結合ます。

関連する問題