2009-08-20 27 views
4

Ich habe ein Projekt, das mich bittet, so eine große Suchmaschine zu machen, die aber allesamt dynamisch ist. Ich meine, ich kann ungefähr 0 bis 9 Hauptgruppen haben, die innerhalb so etwas wie eine unendliche Möglichkeit von "wo" mit "ODER" oder "UND" haben. Das erste, was wir denken, war die Verwendung von Dynamic Linq, die eine gute Alternative zum Erstellen dynamischer Abfragen bieten. All dies mit EF mit einer selbstgemachten Verpackung.Dynamische LINQ für eine Sammlung?

Probleme: Ich kann nicht auf eine "Sammlung" zugreifen. Ich meine, ich kann leicht auf ein referenziertes Objekt zugreifen (wie Customer.State.StateName = "New-York" ODER Custoemr.State.StateName = "Quebec"), aber ich kann keinen Weg zu etwas wie finden : "Customer.Orders.OrderID = 2 ODER Customer.Orders.OrderID = 3". Ich kann das leicht herausfinden, weil es eine Sammlung ist, aber wie kann ich das machen?

Bitte helfen Sie mir !!

** Sorry für mein Englisch !!


aktualisieren

Ich bin genug nicht klar, wie ich glaube, leid sein, weil im französisch ...

Mein Problem sein, weil nichts ist statisch. Es ist eine candidat Suchmaschine für eine regruting compagny, die Kandidaten in ein Unternehmen setzen. Auf einer Seite, auf der der Manager candidat suchen kann, kann er Folgendes analysieren: Domain (s) (Jobs), City (s) oder viele andere, die der Benutzer bei der Registrierung ausgefüllt hat. All dies im Format (wenn es in SQL wäre):

[...] WHERE (Domaine.DomainID = 3 ODER Domaine.DomainID = 5 OR Domaine.DomainID = 23) UND (Städte.CityID = 4, Städte .city = 32) [...]

So kann ich diese wie mit einem normalen LINQ-Format nicht tun:

Candidat.Domaines.Where(domain => domain.DomainID == 3 || domain.DomainID == 5 || domain.DomainID == 23); 

Auch der Betreiber in den paretheses dynamisch sind ("AND" oder „OR ")! Deshalb versuchen wir, Dynamic Linq zu verwenden, weil es viel flexibler ist.

Hoffnung seine einfacher, mein Problem zu verstehen ...


Update 2 meine Methode Hier ist

private string BuildDomainsWhereClause() { 
     StringBuilder theWhere = new StringBuilder(); 

     if (this.Domaines.NumberOfIDs > 0) { 
      theWhere.Append("("); 

      theWhere.Append(string.Format("Domaines.Where(")); 
      foreach (int i in this.Domaines.ListOfIDs) { 
       if (this.Domaines.ListOfIDs.IndexOf(i) > 0) { 
        theWhere.Append(string.Format(" {0} ", this.DispoJours.AndOr == AndOrEnum.And ? "&&" : "||")); 
       } 
       theWhere.Append(string.Format("DomaineId == {0}", i)); 
      } 
      theWhere.Append("))"); 
     } 

     return theWhere.ToString(); 
    } 

Es ist großartig, anstatt funktioniert, dass es "nicht einen boolean zurückgeben". Also wie soll ich? Fehler: "Ausdruck vom Typ 'Boole' 'erwartet".

Am Ende kehrt es so etwas wie: "(Domaines.Where (DomaineId == 2 & & DomaineId == 3 & & DomaineId == 4 & & DomaineId == 5))" die an meine LINQ-Abfrage hinzugefügt:

var queryWithWhere = from c in m_context.Candidats.Where(WHERE) 
            select c; 

Vergessen Sie nicht, dass es wie 7 oder 8 mehr „möglich“ ist hinzugefügt Dinge in suchen ... Irgendwelche Ideen?

Antwort

5

Was Sie hier tun müssen, ist ein LambdaExpression (genauer gesagt ein Expression<Func<T, bool>>) zu bauen. Sie können keine Zeichenfolge verwenden.

ParameterExpression p = Expression.Parameter(typeof(Domaine), "domaine"); 
Expression<Func<Domaine, bool>> wherePredicate = 
    Expression.Lambda<Func<Domaine, bool>>(
    Expression.Or(
     Expression.Equal(
     Expression.Property(p, "DomainID"), 
     Expression.Constant(10)), 
     Expression.Equal(
     Expression.Property(p, "DomainID"), 
     Expression.Constant(11)) 
    ), p); 

heißt

domaine.DomainID = 10 ||: Sie können einen einfachen Ausdruck wie diese bauen domain.DomainID = 11

Nicht gut lesbar, wenn Sie dies von Hand machen müssen.

Es gibt eine Probe eines voll funktionsfähigen Ausdruck Parser, der dies tatsächlich für Sie tun wird basierend auf einer Schnur in C# Samples for Visual Studio 2008 bei MSDN Code Gallery, unter DynamicQuery. (Die LinqDataSource Steuerung verwendet intern eine geringfügig modifizierte Version dieses Beispiels.)

+0

Vielen Dank. Es ist nicht genau das, was ich erwartet habe, aber es sieht gut aus. Ich muss es noch ein bisschen austricksen, um es perfekt dynamisch zu machen. Aber danke, sehr nützlich. –

1

Angenommen, der Kunde.Orders gibt eine Sammlung zurück, genau deshalb können Sie nicht einfach eine Eigenschaft davon aufrufen.

Um LINQ zu verwenden, um die Bestellung Sie suchen zu bekommen, müssen Sie die OrderID (oder eine andere Eigenschaft) wissen, in welchem ​​Fall Sie tun können:

Customer.Orders.Find(order => order.OrderID == 2); 

Edit: Um fügen Sie den Ausdruck id 2 oder 3 auf diese Weise zu finden:

Customer.Orders.FindAll(order => order.OrderID == 2 || order.OrderID == 3); 
1

Habe ich das richtig verstanden, dass beiden Kunden sind eine Sammlung und Bestellungen eine Sammlung ist, während Staat (natürlich) ist eine Eigenschaft?

var q = from a in Customer 
    from b in a.Orders 
    where b.ID == 2 
       || b.ID == 3 
    select b; 

Würde funktionieren, denke ich.

bearbeiten:

Ich habe teilweise so ähnlich. Es ist zu lange her, ganz sicher zu sein, wie ich es tat, aber ich kann Ihnen sagen, dass ich

public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values); 

Von DynamicQueryable Klasse wurde mit.

this.CountrySitesObject.Sites.AsQueryable().Where(w.WhereQuery, w.WhereParameters) 

(von meinem Code kopiert).

+0

Ja, es funktioniert super. Aber nicht, wenn Sie nicht wirklich wissen, wie viele "b.Id" Sie suchen müssen. Auch nicht wenn es ein "||" oder "&&" dazwischen. –

+0

Ich werde das auch versuchen. Aber ich bin auf einer Lösung, die zu funktionieren scheint. Ich komme später zurück, um euch Neuigkeiten zu geben. –

0

Wenn Sie zurücktreten und fragen, was der Kunde tun möchte.

Warum exportieren Sie nicht die Daten zu Excel oder zeigen Sie Excel zu der SQL-Tabelle. Es macht nicht so viel Spaß zu bauen, aber Sie würden in ein paar Stunden statt Tagen oder Wochen fertig sein. :)

+0

Ja, ich weiß !! Aber wir dachten, dass Dynamic LINQ genau das war, wonach wir suchten ... –

3

Endlich habe ich es genau so, wie ich es möchte.

private string BuildDomainsWhereClause() { 
     StringBuilder theWhere = new StringBuilder(); 

     if (this.Domains.NumberOfIDs > 0) { 
      theWhere.Append("("); 

      foreach (int i in this.Domains.ListOfIDs) { 
       if (this.Domains.ListOfIDs.IndexOf(i) > 0) { 
        theWhere.Append(string.Format(" {0} ", this.Domains.AndOr == AndOrEnum.And ? "&&" : "||")); 
       } 
       theWhere.Append(string.Format("Domains.Any(IdDomaine== {0})", i)); 
      } 
      theWhere.Append(")"); 
     } 

     return theWhere.ToString(); 
    } 

, die wie etwas produzieren: "(DispoJours.Any (IdDispo == 3) & & DispoJours.Any (IdDispo == 5))".

Alle meine anderen "Where Builder" werden die gleichen Dinge mit einem "& &" tun, zwischen denen das richtige Ergebnis geben.

Und später:

var queryWithWhere = from c in m_context.Candidats.Where(WHERE) 
        select c; 

WHOOOHOOO !! Danke Leute. Waren sehr nützlich! Liebe diese Webseite!


aktualisieren

Vergessen Sie nicht, dass ich auf dieser Abfrage Dynamische Linq verwenden. Es ist keine normale LINQ-Abfrage.

+2

Wenn Sie tatsächliche Abfragen mit Zeichenfolgen erstellen, stellen Sie sicher, dass Sie die Zeichenfolgen parametrisieren, oder Sie könnten anfällig für SQL-Injection-Angriffe sein. Obwohl es vielleicht der einfachere Weg ist, ist es manchmal nicht unbedingt der beste/sicherste Weg. Wenn Sie LINQ für Ihre Abfragen verwenden, parametrisiert es automatisch Abfragen für Sie. – MunkiPhD

+0

Vielen Dank, um mich zu verhindern. Jetzt, wo wir nicht mehr SQL benutzen, habe ich diese gefährlichen Dinge vergessen. Vielen Dank. Aber in meinem Fall schreibt der Benutzer nicht "1", er wählt es in einer Checkbox-Liste aus, so dass die Gefahr nicht wirklich da ist. Ich werde es trotzdem tun, aber war nicht wirklich eine Gefahr. –