I'm new to EF and I'm trying to use an extension method which converts from my Database type User
to my info class UserInfo
.
I'm using database first if that makes a difference?
My code below gives the error
The operation cannot be completed because the DbContext has been disposed.
try
{
IQueryable<User> users;
using (var dataContext = new dataContext())
{
users = dataContext.Users
.Where(x => x.AccountID == accountId && x.IsAdmin == false);
if(users.Any() == false)
{
return null;
}
}
return users.Select(x => x.ToInfo()).ToList(); // this line is the problem
}
catch (Exception ex)
{
//...
}
I can see why it would do it, but I also don't understand why the result of the where statement isn't being saved into the users
object?
So I guess my main question is why doesn't it work and secondly what's the right way of using extension methods and EF?
This question & answer lead me to believe that IQueryable require an active context for its operation. That means you should try this instead:
try
{
IQueryable<User> users;
using (var dataContext = new dataContext())
{
users = dataContext.Users.Where(x => x.AccountID == accountId && x.IsAdmin == false);
if(users.Any() == false)
{
return null;
}
else
{
return users.Select(x => x.ToInfo()).ToList(); // this line is the problem
}
}
}
catch (Exception ex)
{
...
}
Objects exposed as IQueryable<T>
and IEnumerable<T>
don't actually "execute" until they are iterated over or otherwise accessed, such as being composed into a List<T>
. When EF returns an IQueryable<T>
it is essentially just composing something capable of retrieving data, it isn't actually performing the retrieve until you consume it.
You can get a feel for this by putting a breakpoint where the IQueryable
is defined, vs. when the .ToList()
is called. (From inside the scope of the data context as Jofry has correctly pointed out.) The work to pull the data is done during the ToList()
call.
Because of that, you need to keep the IQueryable<T>
within the scope of the data context.