I just found out that lazy loading in Entity Framework only works from the thread that created the ObjectContext
. To illustrate the problem, I did a simple test, with a simple model containing just 2 entities : Person
and Address
. Here's the code :
private static void TestSingleThread()
{
using (var context = new TestDBContext())
{
foreach (var p in context.Person)
{
Console.WriteLine("{0} lives in {1}.", p.Name, p.Address.City);
}
}
}
private static void TestMultiThread()
{
using (var context = new TestDBContext())
{
foreach (var p in context.Person)
{
Person p2 = p; // to avoid capturing the loop variable
ThreadPool.QueueUserWorkItem(
arg =>
{
Console.WriteLine("{0} lives in {1}.", p2.Name, p2.Address.City);
});
}
}
}
The TestSingleThread
method works fine, the Address
property is lazily loaded. But in TestMultiThread
, I get a NullReferenceException
on p2.Address.City
, because p2.Address
is null.
It that a bug ? Is this the way it's supposed to work ? If so, is there any documentation mentioning it ? I couldn't find anything on the subject on MSDN or Google...
And more importantly, is there a workaround ? (other than explicitly calling LoadProperty
from the worker thread...)
Any help would be very appreciated
PS: I'm using VS2010, so it's EF 4.0. I don't know if it was the same in the previous version of EF...
Is this by design? Yes; any call to Load, implicit or explicit, will eventually go through the ObjectContext
, and ObjectContext is documented to be not thread-safe.
A possible workaround would be to detach the entity from the object context in the worker thread and attach it to an object context in the current thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With