2009-06-16 6 views
11

Ich möchte einen dynamischen where Zustand haben.Wie implementiere ich eine dynamische Where-Klausel in LINQ?

Im folgenden Beispiel:

var opportunites = from opp in oppDC.Opportunities 
        join org in oppDC.Organizations 
         on opp.OrganizationID equals org.OrgnizationID 
        where opp.Title.StartsWith(title) 
        select new 
        { 
         opp.OpportunityID, 
         opp.Title, 
         opp.PostedBy, 
         opp.Address1, 
         opp.CreatedDate, 
         org.OrganizationName 
        }; 

Einige Male habe ich Title und manchmal mache ich nicht. Und ich möchte auch Datum in where Klausel dynamisch hinzufügen.

Zum Beispiel, wie diese SQL:

string whereClause; 
string SQL = whereClause == string.Empty ? 
    "Select * from someTable" : "Select * from someTable" + whereclause 
+1

Denken Sie daran, dass Sie nicht wirklich * schreiben * [T] SQL hier ... Sie schreiben C# –

Antwort

21

Sie können es wie folgt umschreiben:

var opportunites = from opp in oppDC.Opportunities 
          join org in oppDC.Organizations on opp.OrganizationID equals org.OrgnizationID 
          select new 
          { 
           opp.OpportunityID, 
           opp.Title, 
           opp.PostedBy, 
           opp.Address1, 
           opp.CreatedDate, 
           org.OrganizationName 
          }; 

if(condition) 
{ 
    opportunites = opportunites.Where(opp => opp.Title.StartsWith(title)); 
} 

EDIT: Um Ihre Frage in den Kommentaren zu beantworten, ja, können Sie halten Anfügen zum ursprünglichen Abfragbaren. Denken Sie daran, das alles faul ausgeführt, damit an dieser Stelle alle es tut es das IQueryable Aufbau, so dass Sie halten sie zusammen Verkettungs nach Bedarf:

if(!String.IsNullOrEmpty(title)) 
{ 
    opportunites = opportunites.Where(.....); 
} 

if(!String.IsNullOrEmpty(name)) 
{ 
    opportunites = opportunites.Where(.....); 
} 
+0

Ok gut. Kann ich an die where-Klausel anhängen? z.B. if (title! = String.Empty) opportunites = opportunites.Where (opp => opp.Title.StartsWith (title)); if (name! = String.Empty) opportunites = ..... Neuen Namen in vorherigem wo anfügen ????? – Waheed

+0

@Waheed absolut. In der Tat, das Beispiel zeigt, dass Sie die Where-Klausel an das ursprüngliche IQueryable anhängen. Nachfolgende Where-Klauseln haben einen anhängigen Effekt, solange Sie etwas wie opportunities = opportunities machen. Wo (...) – Joseph

+0

Danke, dass ich mein Problem gelöst habe :) – Waheed

5

Sie dynamisch eine where-Klausel zu Ihrem IQueryable Ausdruck wie folgt hinzufügen :

var finalQuery = opportunities.Where(x => x.Title == title); 

und für das Datum ähnlich.

Allerdings werden Sie Ihre anonymen Typ warten müssen, um erstellen, bis Sie dynamisch beendet haben hinzugefügt Ihre where-Klauseln wenn Ihre anonymen Typ enthält nicht die Felder, die Sie in Ihrer where-Klausel abfragen möchten .

So könnten Sie etwas, das wie folgt aussieht:

var opportunities = from opp in oppDC.Opportunities 
        join org in oppDC.Organizations on 
        opp.OrganizationID equals org.OrgnizationID 
        select opp        

if(!String.IsNullOrEmpty(title)) 
{ 
    opportunities = opportunities.Where(opp => opp.Title == title); 
} 

//do the same thing for the date 

opportunities = from opp in opportunities 
       select new 
         { 
          opp.OpportunityID, 
          opp.Title, 
          opp.PostedBy, 
          opp.Address1, 
          opp.CreatedDate, 
          org.OrganizationName 
         }; 
1

Die WHERE-Klausel so etwas wie

//... 
where string.IsNullOrEmpty(title) ? true : opp.Title.StartsWith(title) 
//... 

Dynamisch Rückkehr Aufzeichnungen Ich glaube nicht möglich in LINQ, da es getan werden könnte, ist muss in der Lage sein, einen konsistenten AnonymousType (im Hintergrund) zu erstellen

+0

Sie müssten es überprüfen, aber das kann zu sehr schlechtem TSQL führen (wenn es den Test bis zur Datenbank dauert) –

+0

Guter Punkt - Ich dachte, da es die Ausführung verzögerte, würde es vielleicht nicht stören. – Hugoware

1

Da Abfragen kompostierbar sind, können Sie die Abfrage einfach in Schritten erstellen.

var query = table.Selec(row => row.Foo); 

if (someCondition) 
{ 
    query = query.Where(item => anotherCondition(item)); 
} 
0

Wenn Sie im Voraus wissen, alle möglichen wo Abfragen wie in der SQL-Beispiel Sie gegeben haben Sie die Abfrage wie diese

schreiben
from item in Items 
where param == null ? true : ni.Prop == param 
select item; 

, wenn Sie nicht alle möglichen weißt, wo Klauseln im Voraus Sie können, wo dymically zum Beispiel wie folgt hinzu:

query = query.Where(item => item.ID != param); 
-3

verwenden:

bool DontUseTitles = true; // (Or set to false...  
var opportunites = from opp in oppDC.Opportunities 
        join org in oppDC.Organizations 
         on opp.OrganizationID equals org.OrgnizationID 
        where (DontUseTitles | opp.Title.StartsWith(title)) 
        select new 
        { 
         opp.OpportunityID, 
         opp.Title, 
         opp.PostedBy, 
         opp.Address1, 
         opp.CreatedDate, 
         org.OrganizationName 
        }; 

Warum es funktioniert? Wenn DontUseTitles auf true gesetzt ist, werden alle ausgewählt, weil "(DontUseTitles | opp.Title.StartsWith (title))" als wahr ausgewertet wird. Andernfalls verwendet es die zweite Bedingung und gibt nur eine Teilmenge zurück.

Warum macht jeder die Dinge immer komplexer, als sie sein müssen? :-)

+0

Warum Komplexität? weil OR ist eine schreckliche Sache an die Datenbank zu senden. –

+0

OTOH, zuerst alle Datensätze abrufen, dann die Auswahl auf der In-Memory-Liste ist eine riesige Verschwendung von Ressourcen. Die Verwendung von OR führt zu einer viel kleineren Ergebnismenge. Wenn die Datenbank über 10.000 Datensätze enthält, werden die anderen Antworten alle diese Datensätze zuerst abrufen, bevor sie gefiltert werden. Mein Vorschlag gibt nur diejenigen zurück, die übereinstimmen, was in diesem Fall viel weniger sein kann. –

+1

"Wenn die Datenbank mehr als 10.000 Datensätze enthält, werden die anderen Antworten alle diese Datensätze zuerst abrufen, bevor sie gefiltert werden." Mit Ausnahme der Tatsache, dass aufgrund verzögerter Ausführung die Abfrage, die an die Datenbank gesendet wird, den zusätzlichen Filter enthält und nur die gefilterten Daten zurückgibt. – thornhill

Verwandte Themen