2012-03-23 10 views
2

leer ist habe ich eine Linq subquery wie folgt:Linq prüfen, ob eine Unterabfrage, ohne auf Remote-Datenbank

 for (int i = 0; i < parentAttributes.Length; i++) 
     { 
      Guid parent = parentAttributes[i]; 
      var subQuery = from sc in db.tSearchCluendexes 
          join a in db.tAttributes on sc.AttributeGUID equals a.GUID 
          join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID 
          where a.RelatedGUID == parent && userId == pc.CPSGUID        
          select sc.CPSGUID; 

      query = query.Where(x => subQuery.Contains(x.Id)); 
     } 

Die Grundidee ist, dass ich eine Liste von Daten filtern (wie durch die Abfragevariable dargestellt), basierend auf Die Ergebnisse einer Unterabfrage wurden unbestimmbar oft ausgeführt.

Allerdings habe ich jetzt ein Problem, wobei ich nur wo in der Abfrage ausführen möchte, wenn die Unterabfrage tatsächlich Daten enthält und ich die Unterabfrage nicht innerhalb jeder Iteration der Schleife ausführen möchte (zum Beispiel mit einem Count() oder eine ToList()), da dies die entfernte Ressource trifft. Etwas wie unten, wenn wir annehmen, dass eine Methode HasData() tatsächlich wahr oder falsch zurückgibt:

 for (int i = 0; i < parentAttributes.Length; i++) 
     { 
      Guid parent = parentAttributes[i]; 
      var subQuery = from sc in db.tSearchCluendexes 
          join a in db.tAttributes on sc.AttributeGUID equals a.GUID 
          join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID 
          where a.RelatedGUID == parent && userId == pc.CPSGUID        
          select sc.CPSGUID; 

      if (subQuery.HasData())     
       query = query.Where(x => subQuery.Contains(x.Id)); 
     } 

Vorschläge sind willkommen.

Antwort

4

Ihre Vorschläge zur Verwendung Count und ToList sind nicht der schnellste Weg zu sehen, ob eine Abfrage irgendwelche Ergebnisse hat. Sie sollten die Any Methode verwenden:

if (subQuery.Any()) 
{    
    query = query.Where(x => subQuery.Contains(x.Id)); 
} 

Hinweis, dass dies immer noch sofort ausgewertet werden. Wenn Sie die Ausführung verzögern möchten, sollten Sie sie in die Lambda-Funktion einfügen.

query = query.Where(x => !subQuery.Any() || subQuery.Contains(x.Id)); 
+1

Es gibt keinen Vorteil von der Any innerhalb der Lambda-Ausdruck setzen – Aducci

+0

Danke, ich werde das morgen versuchen. Mit dem Any() im Lambda wird die Ausführung aufgeschoben oder macht es keinen Unterschied wie im Kommentar von Aducci? – kh25

+0

@ kh25: Ich habe nicht dick Auducci sagte, es würde keinen Unterschied machen. Er sagte nur, dass es "keinen Nutzen" geben würde. Ich bin mir nicht ganz sicher, was er damit meint. Vielleicht könnten Sie es testen und uns wissen lassen? –

0

Nach einiger sehr gründliche Überprüfung von Mark Antwort kann ich bestätigen, dass die Any() soll in dem Lambda-Ausdruck sein, da sonst der Code einen Anruf direkt an die Datenbank bei jeder Iteration der Schleife macht (nicht erwünscht).

So Vollständigkeit halber hier ist der Code, den ich verwenden würde vorschlagen, wenn Sie ein ähnliches Problem:

 for (int i = 0; i < parentAttributes.Length; i++) 
     { 
      Guid parent = parentAttributes[i]; 
      var subQuery = from sc in db.tSearchCluendexes 
          join a in db.tAttributes on sc.AttributeGUID equals a.GUID 
          join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID 
          where a.RelatedGUID == parent && userId == pc.CPSGUID        
          select sc.CPSGUID; 


      query = query.Where(x => !subQuery.Any() || subQuery.Contains(x.Id));     
     } 

Dieser Code eine Reihe von existieren Anweisungen an die SQL verketten wird, die schließlich zu einem heißen wird später im Prozess. Wenn Sie die Any() außerhalb des Lambda haben, werden diese SQL-Dateien einzeln aufgerufen.

Danke nochmal Mark - top man.