2016-11-12 5 views
2

Je suis nouveau dans System.Linq.Dynamic.Core. J'ai ceci:System.Linq.Dynamic.Core: Comment faire un select select correctement?

Disons que nous avons:

Packs = new List<Pack> 
{ 
    new Pack() 
    { 
     IdAtSource="Pack1", 
     Equipments= new List<Equipment>() 
     { 
      new Equipment 
      { 
       Id=1, 
       GenericEquipment = new GenericEquipment() 
       { 
        Id=7 
       } 
      } 
     } 
    }, 
    new Pack() 
    { 
     IdAtSource="Pack2", 
     Equipments= new List<Equipment>() 
     { 
      new Equipment 
      { 
       Id=2, 
       GenericEquipment = new GenericEquipment() 
       { 
        Id=1 
       } 
      }, 
      new Equipment 
      { 
       Id=2, 
       GenericEquipment = new GenericEquipment() 
       { 
        Id=2 
       } 
      } 
     } 
    } 
} 

Je voudrais sélectionner le Packs avec Equipments, mais dans le Equipments sélectionné que je dois avoir que celui avec Id=2 pour l'équipement générique. (Le résultat devrait contenir une liste de packs avec la liste des équipements).

J'ai essayé ceci:

querable.Where("Packs.Equipments.Select((GenericEquipment.Id)=1)"); 

mais je sens que je suis waaay la cible ici. Y a-t-il aussi une page de documentation sur l'utilisation de cette bibliothèque?

Merci beaucoup

Répondre

0

La version la plus récente de Dynamic LINQ semble être le projet here, avec la documentation here.


En général, la seule raison pour laquelle vous devriez exiger dynamique LINQ sur LINQ est la norme quand les types sont pas connus au moment de la compilation.

Si vous connaissez au moment de la compilation que la requête sera contre un List<Pack>, vous pouvez utiliser stanadard LINQ, comme dans le code suivant (notez que cela modifie les instances d'origine de Pack):

var usefulPacks = Packs.Select(pack => { 
    pack.Equipments = pack.Equipments.Where(equipment => 
     equipment.GenericEquipment.Id == 1 
    ).ToList(); 
}).Where(pack => pack.Equipments.Any()).ToList(); 

Si vous avez besoin d'un code qui ne modifie pas les instances d'origine, ce code crée des copies des instances d'origine:

var usefulPacks = Packs.Select(pack => { 
    return new Pack() { 
     IDAtSource = pack.IDAtSource, 
     Equipments = pack.Equipments.Where(equipment => 
      equipment.GenericEquipment.Id == 1 
     ).ToList(); 
    }; 
}).Where(pack => pack.Equipments.Any()).ToList(); 

Notez que ce n'utilise pas .SelectMany.SelectMany est utilisé pour créer un seul énumérable à partir des énumératifs imbriqués; ici, chaque Pack dans la liste finale correspond à Pack dans la liste originale.


dynamique LINQ ne prend pas en charge la modification ou l'initialisation des propriétés dans le cadre de l'expression:

Le langage permet d'expression obtenir (mais pas de réglage) la valeur de tout champ public accessible, la propriété ou indexeur.

donc la propriété Equipments ne peut être modifiée/initialisés pour inclure uniquement les instances de Equipment qui correspondent aux critères.

Pour régler la Equipments, vous avez deux choix:

  1. Ajouter un constructeur à Pack qui prend les arguments appropriés
  2. Ecrivez une méthode statique sur une classe qui prend les arguments appropriés

Ajouter un constructeur à Pack

Vous pouvez ajouter un constructeur à Pack avec les arguments appropriés, qui définit Equipments:

Pack(int IDAtSource, IEnumerable<Equipment> equipments) { 
    this.IDAtSource = IDAtSource; 
    this.Equipments = equipments.ToList(); 
} 

Ensuite, vous pouvez utiliser les éléments suivants:

IQueryable qry = Packs.AsQueryable(); 
qry = qry 
    .Select("Pack(IDAtSource, Equipments.Where(GenericEquipment.ID=1))") 
    .Where("Equipments.Any"); 

Définir une méthode statique

public static class MyPackMethods { 
    public static Pack Create(int IDAtSource, IEnumerable<Equipment> equipments) { 
     return new Pack() { 
      IDAtSource = IDAtSource, 
      Equipments = equipments.ToList() 
     }; 
    } 
} 

et appelez:

IQueryable qry = Packs.AsQueryable(); 
qry = qry 
    .Select("MyPackMethods.Create(IDAtSource, Equipments.Where(GenericEquipment.ID=1))") 
    .Where("Equipments.Any"); 
+0

Merci beaucoup pour la réponse! En fait, cela répond presque à ma question. Quand j'ai fini la sélection, j'ai besoin du Pack, avec * juste * les équipements qui ont GenericEqipments avec Id = 1. Signification dans la liste des équipements un seul équipement devrait apparaître. Et aussi, je ne connais pas les types à l'exécution, c'était juste un exemple plus facile à donner comme ça. Merci encore, votre réponse est très utile. – Strawberry

+0

@Strawberry C'est ce qui se passe dans la requête Dynamic LINQ. Nous appelons d'abord '.Select' qui crée une nouvelle instance de' Pack' pour chaque instance initiale de 'Pack', mais ne transmettent que le' Equipement' correspondant au constructeur de la nouvelle instance: 'Equipments.Where (GenericEquipment .ID = 1) '; alors nous appelons '.Where' pour n'inclure que des instances de' Pack' qui ont quelque chose dans la propriété 'Equipments'. –

+0

Compris cher monsieur. Mais malheureusement, ce n'est pas une option pour changer le constructeur, donc je peux utiliser cette solution. – Strawberry

0

Ceux-ci devraient travailler:

var equipments= from pack in Packs where pack.Equipments.Any() select pack.Equipments; 

var secondEquipments = from pac in equipments where  
pac.GenericEquipment.Id == 2 select pac; 
//I could use one variable instead of 2 but that would look a little bit complex 

Msdn Lien (Désolé, je suis au mobile, donc je ne peux pas le renommer): https://msdn.microsoft.com/en-us/library/bb397927.aspx

+0

Merci mon bon monsieur! Pourtant, cela ne répond pas à ma question, sur la façon d'utiliser la bibliothèque Linq.Dynamic.Core. – Strawberry

+0

Pas de problème, mais je pense que cela répond à votre question. Laissez-moi le corriger s'il vous plaît :) –