2010-08-18 15 views
1

Note: I realize this question is similar to another question , however that question was asked in the context of Genom-e and remains unanswered. My question is in the context of LINQ DynamicQuery.en utilisant d'abord() avec OrderBy et DynamicQuery en un à plusieurs tables liées

J'utilise la surcharge de méthode d'extension pour StringOrderBy fourni par System.Linq.Dynamic. Passer une chaîne littérale à OrderBy fonctionne très bien. Je peux trier les champs d'entité primaire, par exemple: person.OrderBy("LastName") et je peux trier les champs d'entités enfants tant qu'il existe une relation un-à-un entre le parent et l'enfant, par exemple: person.OrderBy("Mother.LastName").

Cependant, je suis incapable de trier le champ d'un enfant s'il existe une relation un-à-plusieurs avec le parent et l'enfant, par exemple: person.OrderBy("Children.LastName"). Cela génère une erreur: No property or field 'Children' exists in type 'Person'.

Évidemment, cela échoue parce que l'interprète ne sait pas LastName enfant que j'essaie d'utiliser dans l'opération de tri. Je peux résoudre ce problème facilement en créant une expression comme ceci (Function(p As Person) p.Children.First.LastName).

Mais comment puis-je obtenir un comportement similaire First lors de l'utilisation de l'extension littérale de chaîne de OrderBy? En fin de compte, je veux être en mesure de faire quelque chose comme ceci: person.OrderBy("it.Lastname desc, Children.First().FirstName asc")

Edit: J'utilise le modèle du référentiel et c'est ce que ma fonction Find ressemble à:

Public Function Find(ByVal predicate As Expression(Of Func(Of TEntity, Boolean)), ByVal orderBy As String, ByVal skip As Integer, ByVal take As Integer) As IEnumerable(Of TEntity) Implements ILinqSqlRepository(Of TEntity, TContext).Find 

     If String.IsNullOrEmpty(orderBy) Then 
      Return Find(predicate, skip, take) 
     Else 
      Dim qry = Context.GetTable(Of TEntity)().Where(predicate).OrderBy(orderBy).Skip(skip).Take(take) 
      Return qry.ToList() 
     End If 

    End Function 

Edit: Cette est la relation entre Person et Child tables:

Person Table 
    PersonId (pk) 
    MotherId (fk to Mother Table) 
    LastName 
    FirstName 

Child Table 
    ChildId (pk) 
    PersonId (fk to Person Table) 
    LastName 
    FirstName 

Mother Table 
    MotherId (pk) 
    LastName 
    FirstName 

Chaque Person peut avoir 0 ou plus Children. Vous pouvez voir qu'il peut y avoir 0 ou 1 Mother lignes pour chaque Person.

Il est évident que ceux-ci ne sont pas les noms de tables exactes que je utilise dans mon vrai projet, mais vous pouvez voir comment les relations entre les Person et Mother, et avec Person et Child sont différents.

Sélecteur
J'ai essayé une surcharge Find() d'accepter un Selector qui sélectionne p = Person et child = First().Child mais les changements de type de retour à Anonymous, au lieu du type générique. Y at-il un moyen d'utiliser le Selector dans le processus OrderBy mais toujours retourner un IEnumerable(of TEntity)?

+0

Quelle est la relation entre les tables person and children? –

+0

Modifier: le formatage a été foiré. Il existe des lignes enfant 0-n pour chaque ligne Personne.Par exemple: Table Person: PersonId (pk), Table Child: ChildId (pk), PersonId (fk to Person table), Nom –

Répondre

1

Vous pouvez faire (C#, désolé ...):

people.Select(p => Person = p, Child = p.Children.First()) 
     .OrderBy("Child.LastName") 
     .Select(p => p.Person); 

BTW, sans "it. vous utilisez System.Linq.Dynamic, et "it. vous utilisez ESQL. L'un ou l'autre est OK, mais vous ne devriez pas utiliser les deux!

+0

Craig, merci pour votre commentaire. J'ai manuellement tapé les extraits de code et ajouté accidentellement le 'it.'. Je ne l'utilise pas dans le vrai code. J'ai mis à jour la question pour montrer comment j'utilise le modèle Repository, en passant des prédicats de condition. Je ne suis pas sûr comment ajouter un sélecteur dans la fonction 'Find' et toujours garder la fonction générique. –