Acabo de descubrir que la carga diferida en Entity Framework solo funciona desde el hilo que creó el ObjectContext
. Para ilustrar el problema, hice una prueba simple, con un modelo simple que contiene solo 2 entidades: Person
y Address
. Aquí está el código:La carga diferida de Entity Framework no funciona desde otro hilo
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);
});
}
}
}
TestSingleThread
El método funciona bien, la propiedad Address
se carga con pereza. Pero en TestMultiThread
, obtengo un NullReferenceException
en p2.Address.City
, porque p2.Address
es nulo.
¿Eso es un error? ¿Es esta la manera en que se supone que funciona? Si es así, ¿hay alguna documentación que lo mencione? No pude encontrar nada sobre el tema en MSDN o Google ...
Y más importante aún, ¿hay alguna solución? (Que no sea una llamada explícita a LoadProperty
desde el subproceso de trabajo ...)
Cualquier ayuda sería muy apreciada
PD: estoy usando VS2010, por lo que es EF 4.0. No sé si fue lo mismo en la versión anterior de EF ...
No estoy seguro de su motivación, pero el equipo de .NET parece ser un código alentador que debe escribirse con Tarea y Acción en lugar de hacer un uso explícito del grupo de subprocesos. Tal vez alguien puede proporcionar una buena cita de eso? –
¿Puede explicar un poco el uso de 'p2'? Supongo que no cambió nada? –
@jarrett: tal vez, pero no es el punto ... el problema habría sido el mismo con una tarea, ya que utiliza subprocesos de todos modos. @Henk: tampoco funciona sin 'p2', pero de todos modos es necesario, de lo contrario, cada lambda se cerraría sobre la misma variable; vea este artículo para más detalles: http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –