2

Ich habe die folgenden Methoden:Methode Chaining in EF6 keine Ausgabe die richtige SQL

 private IEnumerable<CTNTransactionsView> RetrieveCTNTransactionsNotInTLS() { 
     IQueryable<int> talismanIdCollection = this._cc.TLSTransactionView.Select(x => x.kSECSYSTrans); 
     return this._cc.CTNTransactionView 
        .Where(x => !talismanIdCollection.Contains(x.kSECSYSTrans)); 
    } 

    public IEnumerable<CTNTransactionsView> RetrieveCTNTransactionsNotInTLSPast24Hours() { 
     DateTime previousDate = DateTime.Now.Date.AddDays(-1.0); 
     return this.RetrieveCTNTransactionsNotInTLS() 
        .Where(x => x.dSECSYSTimeStamp >= previousDate); 
    } 


    public IEnumerable<CTNTransactionsView> RetrieveCTNTransactionsNotInTLSPast24HoursVersionTwo() { 
     DateTime previousDate = DateTime.Now.Date.AddDays(-1.0); 
     IQueryable<int> talismanIdCollection = this._cc.TLSTransactionView 
                .Select(x => x.kSECSYSTrans); 
     return this._cc.CTNTransactionView 
        .Where(x => !talismanIdCollection.Contains(x.kSECSYSTrans)) 
        .Where(x=> x.dSECSYSTimeStamp >= previousDate); 
    } 

Aus irgendeinem Grund die Ausgabe SQL erzeugt durch Entity Framework 6 nicht die Ergebnisse entsprechen.

Die RetrieveCTNTransactionsNotInTLSPast24HoursVersionTwo() -Methode wird ordnungsgemäß eine SQL-Output-Anweisung geben, die Folgendes hat:

select ...... from ... where ...  AND ([Extent1].[dSECSYSTimeStamp] >= @p__linq__0)} 

Der andere hat nicht die Filter für die dSECSYSTimeStamp, wenn ich die SQL-Anweisung Ausgabe anzeigen.

Die Methoden, die ich vergleiche, sind die RetrieveCTNactionsNotInTLSPast24Hours() und die RetrieveCTNtransactionsNotInTLSPast24HoursVersionTwo().

Ich habe die SQL mit VS verglichen sowie eine Debug.Writeline() an das Database.Log im Kontext angehängt.

Vom Debuggen und Betrachten der SQL-Ausgabe scheint einer den Datumsfilter zu enthalten, während der andere nicht und doch beide das richtige Ergebnis liefert.

ich versucht habe, auf der SQL-Suche (durch Setzen von Breakpoints und zu sehen, die Ausgabe) aus mit dem folgenden:

 System.Diagnostics.Debug.WriteLine("Running first method"); 
     var result = this.repo.RetrieveCTNTransactionsNotInTLSPast24Hours(); 
     var count = result.Count(); 
     System.Diagnostics.Debug.WriteLine("Running Second method"); 
     var resultTwo = this.repo.RetrieveCTNTransactionsNotInTLSPast24HoursVersionTwo(); 
     var count2 = resultTwo.Count(); 

Ich bin mit EF 6.0.

Hinweis: Die Ergebnisse sind die gleichen wie beide genau dasselbe tun und das gleiche Ergebnis ausgeben. Allerdings bin ich neugierig und möchte gerne verstehen, warum das SQL Generated nicht das selbe ist?

+2

Der Grund ist, dass LINQ nur LINQ to SQL verwendet, wenn es auf einem IQueryable verwendet wird. 'RetrieveCTNTransactionsNotInTLS' gibt ein IEnumerable zurück. Das bedeutet, dass es zu diesem Zeitpunkt die Daten in den Speicher lädt und dann die zweite Operation 'Where' für die Daten im Speicher ausführt ... nicht durch Ändern der SQL-Anweisung. – David784

Antwort

1

Das Problem ist, dass Sie ein IEnumerable von Ihrer Methode zurückgeben. Wenn Sie dies tun, zwingen Sie SQL, die Abfrage (ungefiltert) auszuführen und dann C# zu verwenden, um dann die zweite Abfrage auszuführen. Ändern Sie Ihre interne Abfrage, um ein IQueryable zurückzugeben. Dadurch kann der nicht ausgeführte Ausdrucksbaum an die zweite Abfrage übergeben werden, die dann bei der Ausführung ausgewertet wird.

heißt

private IQueryable<CTNTransactionsView> RetrieveCTNTransactionsNotInTLS()

Sie sollten dann die gleiche SQL erhalten.

+0

Ich sollte hinzufügen, dass dies nicht immer möglich ist. Ein echter Fehler, den Sie beim Erstellen solcher Filter machen können, ist, dass Sie die SQL-Verbindung nicht schließen können, bevor Sie die Abfrage tatsächlich ausgewertet haben. Wenn Sie das IQueryable zurückgeben, es aber erst viel später im Code auswerten, könnte dieses Problem auftreten. – Spence

0

Ich denke, Sie definieren nur einen Abfrage-Ausdruck, aber es ist nicht sofort zu verwenden, in dieser Zeit, ich .ToList() in dem Linq Ausdruck Ende hinzufügen, aber Sie müssen Methode des Rückgabetyp in eine richtige Art ändern, wie List<kSECSYSTrans> vor dieser Operation. Ich verwende nur selten den Typ IEnumerable.

Verwandte Themen