Ajouter dynamiquement un GroupBy à une expression Lambda

expression-trees linq

Question

Ok, je vous avouerai que je ne "saisis" pas encore complètement les expressions lambda et les arbres d’expression LINQ; Je fais beaucoup de copier / coller et de voir ce qui fonctionne. J'ai parcouru de nombreux documents, mais je n'ai toujours pas trouvé le moment où je me suis "aha".

Cela étant dit ...

J'essaie d'ajouter dynamiquement une expression GroupBy à mon expression Linq. J'ai suivi la question ici: Besoin d'aide pour créer Linq.Expression à Enumerable.GroupBy

et essayé de mettre en œuvre ce que j'ai vu là-bas.

Tout d'abord, j'ai des classes d'entités pour ma base de données, et une table appelée ObjCurLocViewNormalized

J'ai une méthode qui fait l'appel initial,

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

donc je peux appeler:

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

Pas de problème jusqu'à présent.

Maintenant, je veux grouper par une colonne arbitraire, avec un appel comme celui-ci:

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

En ce moment, j'ai une méthode:

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

Tout ça compile bien, mais quand je le lance, j'obtiens l'erreur:

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

et l'erreur vient de cette ligne:

public IQueryable<ObjCurLocViewNormalized> getLocations()
{
    IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
                               select loc);
    return res;
}

Je copie et adapte ce code à partir d'un travail réussi que j'ai réalisé dans des clauses Where dynamiquement ajoutées à une expression. Donc je suis un peu en train de poignarder dans le noir ici.

Si quelqu'un peut aider à faire la lumière sur ce point, il est bien de pouvoir poster un code fonctionnel complet et de réfléchir à ce que je pense pour moi :), mais si vous pouviez expliquer pourquoi cela est faux ou comment envelopper ma tête autour de ces concepts, ce serait génial. Si vous pouvez indiquer une documentation qui peut vraiment aider à combler le fossé entre les bases des expressions lambda et la création d'arborescences d'expression dynamiques, ce serait formidable. Il y a évidemment de gros trous dans mes connaissances, mais je pense que cette information pourrait être utile à d'autres.

merci à tous pour votre temps, et bien sûr si je trouve la réponse ailleurs, je la posterai ici.

Merci encore.

Don

Réponse populaire

La solution devrait être assez simple:

public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>(
    IQueryable<T> source, string column)
{
    PropertyInfo columnProperty = typeof(T).GetProperty(column);
    var sourceParm = Expression.Parameter(typeof(T), "x");
    var propertyReference = Expression.Property(sourceParm, columnProperty);
    var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm);

    return source.GroupBy(groupBySelector);
}

En supposant un exemple de classe comme ceci:

public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>(
    IQueryable<T> source, string column)
{
    PropertyInfo columnProperty = typeof(T).GetProperty(column);
    var sourceParm = Expression.Parameter(typeof(T), "x");
    var propertyReference = Expression.Property(sourceParm, columnProperty);
    var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm);

    return source.GroupBy(groupBySelector);
}

Vous l'invoquez comme ceci:

public static IQueryable<IGrouping<TColumn, T>> DynamicGroupBy<T, TColumn>(
    IQueryable<T> source, string column)
{
    PropertyInfo columnProperty = typeof(T).GetProperty(column);
    var sourceParm = Expression.Parameter(typeof(T), "x");
    var propertyReference = Expression.Property(sourceParm, columnProperty);
    var groupBySelector = Expression.Lambda<Func<T, TColumn>>(propertyReference, sourceParm);

    return source.GroupBy(groupBySelector);
}



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi