2015-05-28 2 views
7

Mit dem folgenden Beispiel enthält:Linq zu Entitäten - SQL Query - Wo Listenobjekt mit 2 Eigenschaften (oder mehr)

var myIds = db.Table1.Where(x=>x.Prop2 == myFilter).Select(x=>x.Id).ToList(); 
var results = db.Table2.Where(x=> myIds.Contains(x.T1)).ToList(); 

Dieser Teil ist einfach.

aber jetzt ist sie vor einem „leichten“ ändern, wo meine „Filterliste“ hat zwei Eigenschaften, anstatt nur eins:

// NOTE: for stackoverflow simplification I use a basic query to 
// get my "myCombinationObject". 
// In reality this is a much more complex case, 
// but the end result is a LIST of objects with two properties. 
var myCombinationObject = db.Table3.Where(x=>x.Prop3 == myFilter) 
            .Select(x=> new { 
              Id1 = x.T1, 
              Id2 = x.T2 
            }).ToList(); 

var myCombinationObjectId1s = myCombinationObject.Select(x=>xId1).ToList(); 
var myCombinationObjectId2s = myCombinationObject.Select(x=>xId2).ToList(); 

// step#1 - DB SQL part 
var resultsRaw = db.Tables.Where(x=> 
        myCombinationObjectId1s.Contains(x.Prop1) 
        || myCombinationObjectId2s.Contains(x.Prop2)) 
       .ToList(); 
// step#2 - Now in memory side - where I make the final combination filter. 
var resultsFiltered = resultsRaw.Where(x=> 
      myCombinationObject.Contains( 
         new {Id1 = x.Prop1, Id2 = x.Prop2 } 
      ).ToList(); 

Meine Frage: ist es sogar möglich, den Schritt # fusionieren 2 in Schritt # 1 (Query in Entitäten)?

+0

Leider ist es komplexes Problem .. Bitte meine Frage gelesen - vielleicht wird etwas nützlich sein: http://stackoverflow.com/questions/25563338/linq-simulating-multiple-columns-in-in-clausule –

Antwort

2

I‘ Sie haben es geschafft, das zu tun, was Sie wollen, aber es ist ziemlich schwierig und erfordert ein etwas anderes Modell. Sie benötigen eine Entity, um den Typ

new {Id1 = x.Prop1, Id2 = x.Prop2 } 

zuzuordnen. Sie brauchen also zwei Eigenschaften - Id1 und Id2. Wenn Sie eine haben - toll, wenn nicht, dann diese Stelle Modell hinzufügen:

public class CombinationObjectTable 
{ 
    public virtual Guid Id1 { get; set; } 
    public virtual Guid Id2 { get; set; } 
} 

Fügen Sie es zu Ihrem Modell:

public DbSet<CombinationObjectTable> CombinationObjectTable { get; set; } 

Erstellen neuer Migration und wenden es Datenbank (Datenbank jetzt zusätzliche haben Tabelle CombinationObjectTable). Danach fangen Sie an, eine Abfrage zu erstellen:

DbSet<CombinationObjectTable> combinationObjectTable = context.Set<CombinationObjectTable>(); 
StringBuilder wholeQuery = new StringBuilder("DELETE * FROM CombinationObjectTable"); 
foreach(var obj in myCombinationObject) 
{ 
    wholeQuery.Append(string.Format("INSERT INTO CombinationObjectTable(Id1, Id2) VALUES('{0}', '{1}')", obj.Id1, obj.Id2); 
} 
wholeQuery.Append(
    db.Tables 
     .Where(x=> 
       myCombinationObjectId1s.Contains(x.Prop1) 
       || myCombinationObjectId2s.Contains(x.Prop2)) 
     .Where(x=> 
      combinationObjectTable.Any(ct => ct.Id1 == x.Id1 && ct.Id2 == x.Id2) 
     ).ToString(); 
    ); 

var filteredResults = context.Tables.ExecuteQuery(wholeQuery.ToString()); 

Dank dieser bleibt Ihre Hauptabfrage in linq geschrieben. Wenn Sie Ihrer Datenbank keine neue Tabelle hinzufügen möchten, ist dies ebenfalls möglich. Fügen Sie dem Modell eine neue Klasse CombinationObjectTable hinzu, generieren Sie eine neue Migration, um es hinzuzufügen, und entfernen Sie anschließend den Code, der diese Tabelle aus dem Migrationscode erstellt. Danach wenden Sie die Migration an. Auf diese Weise wird das Datenbankschema nicht geändert, aber EF wird denken, dass CombinationObjectTable in der Datenbank vorhanden ist. Statt es müssen Sie eine temporäre Tabelle erstellen, um Daten zu halten:

StringBuilder wholeQuery = new StringBuilder("CREATE TABLE #TempCombinationObjectTable(Id1 uniqueidentifies, Id2 uniqueidentifier);"); 

Und wenn Sie ToString-Methode auf Ihrer Linq-Abfrage ändern CombinationObjectTable zu #TempCombinationObjectTable aufzurufen:

... 
.ToString() 
.Replace("CombinationObjectTable", "#TempCombinationObjectTable") 

Andere Sache eine Überlegung wert wäre Verwenden Sie Query-Parameter, um Werte in INSERT-Anweisungen zu übergeben, anstatt sie nur in die Abfrage selbst aufzunehmen - dies ist natürlich auch mit EF möglich. Diese Lösung ist nicht vollständig bereit für die Anwendung, sondern ein Hinweis darauf, in welche Richtung Sie für die Lösung gehen können.

2

Können Sie etwas tun, wie folgt aus:

var result= 
     db.Tables 
      .Where(t=> 
       db.Table3 
       .Where(x=>x.Prop3 == myFilter) 
       .Any(a=>a.T1==t.Prop1 || a.T2==t.Prop2) 
     ).ToList(); 
+0

Basierend auf meine Frage, wo ich mein Problem mit dem myCombinationObject vereinfacht habe (einfacher zu stackoverflow migrieren), ja, ich würde ja sagen, es ist eine richtige Antwort. In Wirklichkeit stammt mein myCombinationObject jedoch NICHT von db.Table3, ist stattdessen das Ergebnis einer anderen komplexen LOONNNGGG-Abfrage, wo sogar "lets vom Typ" let temp1 = xxxxxx "und so weiter ... und dafür habe ich immer noch keine Lösung .... Irgendwie Ich danke Ihnen für die Antwort Ich werde es definitiv in Zukunft für andere Fälle verwenden.) – Dryadwoods

1

Wenn Sie einfach nur das Zwischenergebnis vermeiden wollen (und auch einen zweiten Vermittler Liste erstellen) können Sie die folgende

tun
var resultsFiltered = db.Tables.Where(x=> 
       myCombinationObjectId1s.Contains(x.Prop1) 
       || myCombinationObjectId2s.Contains(x.Prop2)) 
      .AsEnumerable() // everything past that is done in memory but isn't materialized immediately, keeping the streamed logic of linq 
      .Where(x=> 
       myCombinationObject 
        .Contains(new {Id1 = x.Prop1, Id2 = x.Prop2 }) 
      .ToList(); 
+0

Ich schätze Ihre Hilfe, aber Sie liefern mir keine Antwort auf meine Frage (nur eine Frage LINQ TO ENTITIES). – Dryadwoods

+0

@ Dryadwoods Es würde viel einfacher zu sagen, ob alles in einer Abfrage erledigt werden kann, wenn wir die tatsächliche "nicht für Stackoverflow" Version Ihres Codes vereinfacht haben, wenn Sie alles auf der DB-Seite tun wollen, müssen wir wissen, was Sie ' genau das tun –

Verwandte Themen