Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reuse LINQ select function

I have the following code:

internal static IQueryable<UserModel> SelectUser(this IQueryable<User> query, bool getChildren) {
    log.DebugFormat("create the select statement for an individual user {0}", getChildren ? "with children" : "without children");
    var res = query.Select(u => new UserModel {
        // [...] unimportant stuff
        Groups = u.Groups.Select(g => new GroupModel {
            Name = g.Name,
            Description = g.Description,
            ID = g.ID
        }).Take(10),
        CreatedGroups = !getChildren ? null : u.CreatedGroups.Select(g => new GroupModel {
            Name = g.Name,
            Description = g.Description,
            ID = g.ID
        }).Take(10)
        // [...] more stuff like above just different types
    });
    return res;
}

This code works perfectly. But I am a bit annoyed, that I am violating the DRY principle with this code. Most important, there are way more situations, where I need to map a Group to a GroupModel.

So I decided to create an extension method:

public static IEnumerable<GroupModel> SelectChildGroups(this ICollection<Group> query) {
    return query.Select(g => new GroupModel {
        Name = g.Name,
        ID = g.ID
    });
}

And this gives me the following exception:

'LINQ to Entities' erkennt die Methode 'System.Collections.Generic.IEnumerable`1[Coding.Lizards.Gekkota.Web.Models.GroupModel] SelectChildGroups(System.Collections.Generic.ICollection`1[Coding.Lizards.Gekkota.Web.Models.Group])' nicht, und diese Methode kann nicht in einen Speicherausdruck übersetzt werden. 

In English:

'LINQ to Entities' does not recognize the method 'System.Collections.Generic.IEnumerable`1[Coding.Lizards.Gekkota.Web.Models.GroupModel] SelectChildGroups(System.Collections.Generic.ICollection`1[Coding.Lizards.Gekkota.Web.Models.Group])', and this method cannot be translated into a store expression. 

I was able to trace the error down to the function that I posted. Does anybody know how to fix it?

EDIT

The properties Groups and CreatedGroups are of type ICollection<Group>. And the code is used with Linq-To-Entities.

like image 644
Knerd Avatar asked Jun 07 '26 06:06

Knerd


1 Answers

Try storing the Func in a variable, and re-use it. Something like this:

internal static IQueryable<UserModel> SelectUser(this IQueryable<User> query, bool getChildren) {
    log.DebugFormat("create the select statement for an individual user {0}", getChildren ? "with children" : "without children");

    var res = query.Select(u => new UserModel {
        // [...] unimportant stuff
        Groups = u.Groups.AsQueryable().Select(MyLinqExpressions.fSelect).Take(10),
        CreatedGroups = !getChildren ? null : u.CreatedGroups.AsQueryable().Select(MyLinqExpressions.fSelect).Take(10)
        // [...] more stuff like above just different types
    });
    return res;
}

Then another class:

public static class MyLinqExpressions {
    public static Func<Group,GroupModel>
        fSelect = g => new GroupModel {
            Name = g.Name,
            Description = g.Description,
            ID = g.ID
        };
}
like image 100
Guillermo Gutiérrez Avatar answered Jun 09 '26 01:06

Guillermo Gutiérrez