2017-07-19 5 views
0

Ich muss eine Migration von einer Datenbank (O) zu einem anderen von bestimmten Daten, die nicht in der endgültigen Datenbank (D) ist, eine der Probleme ist, dass die Datenbank Tabellen hat differents Namen in Feldern. Ich habe versucht, die Daten zu tun bekommen, die nicht in D Datenbank mit:Schlechte Leistung mit Ausnahme zu groß in 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); 

Als ich versuchte, einen für jeden oder rowsNotMatch.Count() zu tun, es dauert zu lange ...

Meine Lösung war mit SqlQuery von einer Abfrage, die die dismatch-Zeilen abruft (mehr weniger 5 Sekunden, hängt von Siz der Datenabweichung ab). Aber ich würde gerne wissen, ob es einen anderen Weg mit EF gibt, wie meinen Code, aber das wird nicht eingefroren.

Antwort

1

Das sieht so aus, als ob Sie 2 Tabellen in 2 verschiedenen dbContexts öffnen, 2 Tabellen basierend auf 2 Spalten in jeder Tabelle vergleichen, die Zeilen in der Originaltabelle finden, die keine Übereinstimmung haben. EF zu verwenden, um so etwas zu tun, wäre nicht meine Empfehlung. Es wäre viel besser, dies in den Datenbank/W-Tabellen zu tun. Indem Sie .AsEnumerable() jeder Tabelle ausführen, laden Sie den gesamten Inhalt dieser Tabellen in den Speicher.

Wenn Sie müssen etwas tun, wie dies in Code: Ich habe etwas wie betrachten würde:

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

Wenn diese Zieltabelle groß sein soll, dann sollten Sie dies auf den Seiten von 1000 durchführen oder also mit .Skip() und .Take().

Der nächste Schritt wäre, alle Zeilen in eine Puffertabelle im Ursprungs-DB einzufügen. Die Puffertabelle enthält die PK der Zielzeile und die Kriterien für die Übereinstimmung.

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

würde ich einen separaten DbContext für diese eher als die Herkunft ein, empfehlen ohne Änderungsverfolgung zu initialisieren, und zunächst in der Tabelle tempx alle Datensätze löschen. Wenn Sie> 1000 Zeilen einfügen, möchten Sie dies in Stapeln von 1000, saveChanges tun, dann den Kontext mit jedem Stapel entsorgen und neu erstellen, um die Operationen schnell zu halten. Der Ursprung dbContext muss auch über TempX wissen, nur nicht für die Bevölkerung.

Sobald die Datensätze in der tempx Tabelle auf dem Quellschema:

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

Auch wenn es viele nicht-Matches erwartet wird, dann eher als der .ToList() verwenden, um ein .skip() und .Take() Ansatz.

Wenn dies etwas ist, das möglicherweise mehr als einmal in einer bestimmten Datenbank ausgeführt werden könnte, würde ich hoffentlich auch etwas wie einen CreatedAt/ModifiedAt dateTime-Wert haben, mit dem ich für die Origin- und Zieldatenbanken filtern könnte . I.e. Aufzeichnen der letzten Ausführung von DateTime und Filtern von Zeilen aus beiden Abfragen basierend auf> LastRunDate, um die Anzahl der gezogenen und verglichenen Zeilen zu reduzieren.

+0

Danke Steve Py! – kartGIS

1

versuchen, etwas wie folgt aus:

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 

Dies macht im Wesentlichen eine linke Verknüpfung zwischen dtOrigin und dtDestiny, Rückkehr nur die Elemente in dtOrigin, die kein Spiel in dtDestiny haben.