Nous construisons des expressions de recherche dynamique à l'aide de la bibliothèque Dynamic Linq. Nous avons rencontré un problème avec la façon de construire une expression lamba à l'aide de la bibliothèque dynamique linq pour les propriétés de navigation qui ont une relation un à plusieurs.
Nous avons ce qui suit que nous utilisons avec une instruction contient-
Person.Names.Select(FamilyName).FirstOrDefault()
Cela fonctionne mais il y a deux problèmes.
Bien sûr, il ne sélectionne que le nom FirstOrDefault (). Nous voulons qu'il utilise tous les noms de chaque personne.
S'il n'y a pas de nom pour une personne, le Select lève une exception.
Ce n'est pas si difficile avec une requête régulière car nous pouvons en faire deux à partir d'instructions, mais l'expression lambda est plus difficile.
Toute recommandation serait appréciée.
EDIT - Informations supplémentaires sur le code ... une expression linq non dynamique ressemblerait à ceci.
var results = persons.Where(p => p.Names.Select(n => n.FamilyName).FirstOrDefault().Contains("Smith")).ToList();
et la classe ressemble à ce qui suit-
public class Person
{
public bool IsActive { get; set;}
public virtual ICollection<Name> Names {get; set;}
}
public class Name
{
public string GivenName { get; set; }
public string FamilyName { get; set; }
public virtual Person Person { get; set;}
}
Nous l'avons hachée et l'avons fait, mais c'était assez difficile. Voici les différentes méthodes sur la façon dont nous avons progressé vers le résultat final. Il ne nous reste plus qu'à repenser la façon dont notre classe SearchExpression est construite ... mais c'est une autre histoire.
1. Syntaxe de requête équivalente
var results = from person in persons
from name in person.names
where name.FamilyName.Contains("Smith")
select person;
2. Syntaxe Lambda équivalente
var results = persons.SelectMany(person => person.Names)
.Where(name => name.FamilyName.Contains("Smith"))
.Select(personName => personName.Person);
3. Syntaxe lambda équivalente avec Dynamic Linq
var results = persons.AsQueryable().SelectMany("Names")
.Where("FamilyName.Contains(@0)", "Smith")
.Select("Person");
Remarques - Vous devrez ajouter une méthode Contains à la bibliothèque Dynamic Linq.
EDIT - Alternativement, utilisez simplement une sélection ... beaucoup plus simple ... mais cela nécessite l'ajout de la méthode Contains comme indiqué ci-dessus.
var results = persons.AsQueryable().Where("Names.Select(FamilyName)
.Contains(@0", "Smith)
Nous avons d'abord essayé cela, mais nous sommes tombés sur la redoutable `` Aucune méthode d'agrégation applicable Contient existe ''. Erreur. J'ai fait un tour sur la façon dont nous avons résolu le problème en essayant de faire fonctionner SelectMany ... donc je suis juste revenu à la méthode Select.