Why is my result of type List<IEnumerable<T>>
Two queries that should result in a list of account numbers (strings). However the second query actually returns a List<IEnumerable<string>>
, where I would like it to return a List<string>
. What am I doing wrong?
//the type here resolves to List<string>
var acts = (from a in base.context.Accounts
select a.Acco开发者_开发百科untNumber).ToList();
//the type here resolves to List<IEnumerable<string>>
var uAccounts = (from u in base.context.Users
select u.Accounts.Select(s => s.AccountNumber)).ToList();
Change
var uAccounts = (from u in base.context.Users
select u.Accounts.Select(s => s.AccountNumber)).ToList();
to
var uAccounts = base.context.Users.SelectMany(u =>
u.Accounts.Select(s => s.AccountNumber)).ToList();
And to actually answer your question, the difference between the two lines of your code is that the first one goes through every single account and selects just the account number. The second statement selects an embedded Linq query of IEnumerable<string>
. So you are converting to a List<T>
of these IEnumerable<string>
That actually shows the benefit of the SelectMany extention method (I'm not actually sure about how to use that in a query statement). The SelectMany method instead flattens the IEnumerable<T>
you would normally receive to a single enumeration of the T
element. So when ToList()
is called, it will return you a List<string>
instead of the enumerable.
Your select
clause is returning / nests another select
operation and hence you end up with nested enumerations. To flatten the list you need to use SelectMany
instead.
var acts = base.context.Accousts
.SelectMany(a => x.AccountNumber)
.ToList();
u.Accounts.Select(s => s.AccountNumber)
by itself gives you an IEnumerable<string>
.
Then wrapping that in from u in base.context.Users select u.Accounts.Select(s => s.AccountNumber)
gives you an IEnumerable<IEnumerable<string>>
.
Then calling .ToList()
on that gives List<IEnumerable<string>>
.
While you could use SelectMany
, it is more straightforward to nest your from clauses:
var uAccounts = (from u in base.context.Users
from a in u.Accounts
select a.AccountNumber).ToList();
When and if you use products like NHibernate, you will want to know this idiom, as it is a very straightforward way to do table joins in the resulting SQL code.
In the second query, you are doing a second select that's creating your inner list
This returns an IEnumerable<string>
u.Accounts.Select(s => s.AccountNumber)
and then your are wrapping it in another select that creates the outer list
u.Accounts.Select(s => s.AccountNumber)
is a list of Account number
so
(from u in base.context.Users
select u.Accounts.Select(s => s.AccountNumber))
is an IEnumerable of lists of account numbers
adding .ToList()
Makes it a List of lists of account numbers
I think I need to use u.Accounts.SelectMany(...)
to get the desired result.
In the second case, the ToList()
only applies to the outer list, which itself consists of lists.
u.Accounts.Select(s => s.AccountNumber)
returns IEnumerable<string>
select u.Accounts.Select(s => s.AccountNumber)
returns IEnumerable<IEnumerable<string>>
select u.Accounts.Select(s => s.AccountNumber)).ToList();
just turns the outer IEnumerable into IList
精彩评论