简体   繁体   中英

Linq Query returning IQueryable<IEnumerable<User>> not IQueryable<User>

I'm in the process of refactoring my EF Repository classes to make them testable, following the advice from this excellent blog post:

https://blog.iannelson.uk/testing-linq-queries/

All is good and I am able also able to chain the IQueryable extension methods like in the blog post making things much more conscience and easier to read.

I have come across a hurdle relating to an associated List<> .

The domain entity is a User, and a user has a collection of Friends of type List<User> - standard social networking paradigm.

I want to search a subset of a users friends, say all the friends whose username begins with 'a'. So I do this:

    public static IQueryable<IEnumerable<User>> SelectFriendsUsernameStartsWith(this IQueryable<User> userQueryable, string searchQuery)
     {
        return userQueryable.Select(x => x.Friends.Where(y => y.Username.StartsWith(searchQuery)));
     }

The problem is that this breaks my chaining. The return type is no longer IQueryable<User> its IQueryable<IEnumerable<User>> so the extension methods I wrote for IQueryable<User> can't be chained onto the end.

The type difference here doesn't make any sense to me since in my unit tests I have code that looks like this:

            IEnumerable<User> users = new HashSet<User>()
                                    {
                                        new User() {Username = "Aaron"},
                                        new User() {Username = "alex"},
                                        new User() {Username = "Ally"},
                                        new User() {Username = "anthony"},
                                        new User() {Username = "bob"},
                                        new User() {Username = "Bill"}
                                    };

        IQueryable<User> userQueryable = users.AsQueryable();

ie Calling AsQueryable() on an IEnumerable<User> returns an IQueryable<User> not (as in the example above) an IQueryable<IEnumerable<User>>

Can anyone shed any light on this?

What's the really difference between the two types and how do I force my example above to return me an IQueryable<User> not IQueryable<IEnumerable<User>> ?

Thanks!

Change userQueryable.Select(... to userQueryable.SelectMany(...

Currently your query does something like this:

"For each user, get me a list of all of their friends that start with something"

so you have a list of lists, so to speak. SelectMany is a way of saying, "turn each thing in this list into a sequence of things, and then concat those sequences together. The result is one big long list of things, rather than a list of lists of things.

(When I say "list" in this reply I really mean sequence, ie IEnumerable/IQueryable.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM