I\'m writing some code to access a database using EntityFrameWork. The code is:
public IEnumerable GetRows(int id)
{
using (var context = new
The reason you need to call ToList
, ToArray
, or some other method that enumerates the data returned by EF is that query execution in LINQ is deferred: the data is not processed until you take it explicitly. By the time your method returns the context through which the query data has been obtained is closed (your using
block takes care of that happening quickly), causing the exception that you see.
This is done so that the code is not spending time processing the data that you do not need. For example, you could write code that starts reading through the data on the client side, and stops in the middle. If query execution were not deferred, you would have spent time and memory obtaining the "tail" of the query only to throw it away. Deferred execution puts you in control: you decide what data you want to keep as you go, or bring the entire collection to memory based on what you plan to do with the data.
If you don't call .ToList()
the enumerable will be evaluated after your using
clause finishes, and thus the data context will be disposed before evaluating the query.
IMO, you should consider making your repository handle this (by calling .ToList()
) as otherwise this issue is representative of an implementation detail leaking out.
Without ToList()
you only return enumerator not actual collection of objects. The actual objects are fetched when you try to access the collection. But in this case what you need is a context and repository, because you accessing them from the database. But since it's already out of scope of the using
clause both are disposed hence the exception.
I assume ToList() is deep copying the object
Not exactly - before you call ToList
all you have is a query. you don't get the results until you enumerate it or turn it into a concrete collection via ToList
, ToArray
, etc
.
surely the original object should be usable?
Nope - it's been disposed, which is your way of telling the system that the object has done its job and is no longer needed. The fact that you still have an unexecuted query does not keep the context in a usable state.