Your confusion as far as having them on the same line seems to be on how it's applying the await
. This should work fine:
var languages = (await _unitOfWork.Languages.All()).OrderBy(x => x.Order);
You need to do this because your All
function is returning a Task
while OrderBy
is not.
Additionally, you probably don't want to call .ToListAsync()
in the first place, that's just a SELECT *
without any limit or where clause which may not be the "end of the world" all the time but often will be extremely detrimental to your performance.
As for your second question about why it's returning an IEnumerable<T>
it's because List<T>
implements IEnumerable<T>
and your function signature indicates that it returns IEnumerable<T>
public virtual async Task<IEnumerable<T>> All()
I highly recommend instead of ever dealing with .ToListAsync
or IEnumerable<T>
you leave it alone and let IQueryable<T>
do its proper work against the database.
EDIT: It's been asked in comments why it matters that you'd use IQueryable<T>
. The answer is because utilizing .Where
, .Any()
etc... against IQueryable
will mold the underlying query against the DB.
For example, say you want to find a single entity with the Id
of 123
. If you leave your .ToListAsync()
without any other modifications it will pull back every single row in the DB into your program in memory and then iterate every single row looking for that one row.
If, instead, you use IQueryable<T>
- at the point where you apply .FirstOrDefault(e => e.Id == 123)
it will be applied to the database and it will apply as something like SELECT TOP(1) * FROM MyEntity WHERE [Id] = 123
- pulling back a single row instead of every row in existence.
EDIT2: Note that this also applies to projection. This means something like .Select(e => new { FullName = e.FirstName + " " + e.LastName, State = e.Address.State})
will only pull those 2 columns instead of all columns and any nav properties you include. Doing that after a .ToList()
or .ToListAsync
will instead pull back all columns/entities and iterate over them to create a whole new set of other entities. This can result in MASSIVE CPU/Memory differences between the 2 approaches.