7
votes

Dynamic Linq - Effectuer une requête sur un objet avec des membres de type "dynamique"

J'essaie d'utiliser une requête Dynamic Linq pour récupérer un iEnumerable à partir d'une collection d'objets (Linq à l'objet), chacun des objets de la collection a une collection interne avec un autre ensemble d'objets où les données sont stockées. Ces valeurs sont accessies via un indexeur de la collection extérieure

La requête Dynamic Linq renvoie le jeu filtré comme prévu lorsque vous travaillez avec des objets fortement typés, mais mon objet stocke les données dans un membre de type dynamique , veuillez consulter l'exemple ci-dessous: xxx

Quand j'exécute l'exemple ci-dessus, je reçois: Opérateur '==' Incompatible avec les types d'opérande "Objet" et ' Int32 '

sont membres dynamiques incompatibles avec des requêtes dynamiques de Linq?, Ou existe-t-il une autre façon de construire des expressions qui évalueraient correctement lorsqu'il s'agit de membres du type Dynamique

Merci beaucoup pour votre aide.


0 commentaires

3 Réponses :


3
votes

sont Membres dynamiques forts> incompatibles avec des requêtes Dynamic Linq?, ou y a-t-il une autre façon de construire des expressions qui évalueraient correctement lorsqu'ils traitent avec des membres de type dynamique for forte>? P >

Les deux peuvent travailler ensemble. Juste faire une conversion en int32 avant de faire la comparaison comme: p> xxx pré>

EDIT 1: strong> ayant dit que, l'utilisation d'une liaison dynamique en relation avec LINQ est restreint en général comme des opérations dynamiques ne sont pas autorisées dans les arbres d'expression. Considérez la requête LINQ-TO-Objections suivante: P>

// Variant 2: Detecting the type at runtime.
public void DynamicQueryExample(string property, string val)
{
    List<DataItem> repository = new List<DataItem>(){
        new DataItem() {
            new Data("Name", "Mike"),
            new Data("Age", 25),
            new Data("BirthDate", new DateTime(1987, 1, 5))
        },
        new DataItem() {
            new Data("Name", "Steve"),
            new Data("Age", 30),
            new Data("BirthDate", new DateTime(1982, 1, 10))
        }
    };

    string whereClause = "{0}(it[\"{1}\"]) == {2}";


    // Discover the type at runtime (and convert accordingly)
    Type type = repository.First()[property].GetType();
    string stype = type.ToString();
    stype = stype.Substring(stype.LastIndexOf('.') + 1);

    if (type.Equals(typeof(string))) {
        // Need to surround formatting directive with ""
        whereClause = whereClause.Replace("{2}", "\"{2}\"");
    }
    string predicate = String.Format(whereClause, stype, property, val);

    var result = repository.AsQueryable<DataItem>().Where(predicate);
    if (result.Count() == 1)
        Console.WriteLine(result.Single()["Name"]);
}

var p = new Program();
p.DynamicQueryExample("Age", "30");
p.DynamicQueryExample("BirthDate", "DateTime(1982, 1, 10)");
p.DynamicQueryExample("Name", "Mike");


5 commentaires

Ensuite, ils ne sont pas vraiment «compatibles» sont-ils?


Merci, ces solutions fonctionnent bien lorsque nous connaissons à l'avance le type d'exécution de la valeur, mais que diriez-vous du moment où la requête est construite par programme, nous ne saurons pas vraiment comment convertir les valeurs avant la main. Y a-t-il une autre solution dans laquelle une expression peut être construite?


@ M.babcock: dépend de votre définition de "compatible".


Merci beaucoup, les deux variantes semblent bien fonctionner. Y a-t-il une différence en termes de performance entre les deux solutions?


Et si val.tostring () est évalué à une chaîne avec " ou` \ `



1
votes

Avez-vous essayé it [\ "\" \ \ "]. Equals (objet (30)) code>?

tel que: P>

IEnumerable<DataItem> result = 
    repository.AsQueryable<DataItem>().Where("it[\"Age\"].Equals(object(30))");


2 commentaires

Cela jette une exception "Expression de type" System.int32 'ne peut pas être utilisée pour le paramètre de type "System.Object" de la méthode "Boolean Equals (System.Object)" ". il [\ "\" \ \ "]. Equals (objet (30)) fonctionne, cependant.


Merci, cette solution fonctionne également bien. Toute considération de performance entre cette solution et celles données par @afrischke



1
votes

est le code ci-dessous utile pour vous? XXX

Mais pour que cela fonctionne, tous vos types pouvant être affectés à la valeur de votre Données La classe doit avoir une implémentation utile de la méthode tostring .


0 commentaires