Reputation: 2880
If I only have to use that result one time i.e. in iterating and displaying in view. I generally do 1st one, is it wiser?
IEnumerable<model> result = _someService.GetValues();
return View(result);
OR
IList<model> result = _someService.GetValues().ToList();
return View(result);
I checked in profiler and db is queried only once for that data using EF6.
To clear its a plain SELECT and both has data and there is no adjacent list to kick in lazy loading.
Note: I know IEnumerable has one method GetEnumerator which executes everytime its called it executes for data whereas ToList() executes only once.
Upvotes: 0
Views: 576
Reputation: 151674
See Programmers.SE: Why should I use List<T>
over IEnumerable<T>
?:
There are times when doing a ToList() on your linq queries can be important to ensure your queries execute at the time and in the order that you expect them to.
This is exactly the case here.
If _someService.GetValues()
returns an IEnumerable<model>
which is an Entity Framework query through deferred execution, calling ToList()
in your controller will execute the query there: in your controller, where you can handle the exceptions that may occur. For example a query timeout.
If you don't call .ToList()
, that same exception will be thrown instead at @foreach (var item in Model)
in your view. You don't want that.
Also, if you use lazy loading, the context will be disposed by the time the query result end up in your view and throw an exception again, so in that case you'll have to materialize the query results in your controller by calling .ToList()
.
People get all high up in a tree when it comes to IEnumerable<T>
versus IList<T>
. They are generally parroting each other from some general advice (found here, amongst others), but they do not understand that that advice is for API design. You are not designing an API, you are implementing an application with very specific requirements: the view may never throw an exception. In order to fulfill that requirement, you must execute your queries in your controller, hence call .ToList()
there.
The user asking the question linked above is right in the comment they posted:
all queries should be executed so that the model is done and loaded ready for the view. I.e. the view should receive everything and not be querying the database.
Razor rendering your model to your view may not have any side-effects. Executing a query is a side-effect, so that may not happen while rendering your view.
Even when calling .ToList()
in your controller, your @model
directive in the view can and should still be of IEnumerable<T>
though!
Upvotes: 4