2

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();

i.e. 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!

4

1 回答 1

7

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, i.e. IEnumerable/IQueryable.)

于 2012-05-03T17:11:24.240 回答