2010-04-04 8 views
7

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 ...

+1

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? –

+0

¿Puede explicar un poco el uso de 'p2'? Supongo que no cambió nada? –

+0

@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 –

Respuesta

7

¿Es esto por diseño? Sí; cualquier llamada a Load, implícita o explícita, eventualmente pasará por ObjectContext y ObjectContext is documented to be not thread-safe.

Una posible solución sería separar la entidad del contexto del objeto en el hilo del trabajador y adjuntarla al contexto de un objeto en el hilo actual.

+0

Gracias por su respuesta. Desafortunadamente, en mi caso, crear otro contexto de objeto definitivamente es excesivo. Estoy tratando de cargar imágenes en una aplicación WPF utilizando un enlace asíncrono, y realmente no quiero crear un nuevo contexto para cada imagen (aproximadamente 150 imágenes actualmente) –

+0

Creo que en este punto tienes una pregunta WPF , no una pregunta EF. Las reglas de EF son muy simples. Cómo seguirlos usando WPF es otro problema. –

+0

Bueno, lo estoy usando en WPF, pero no es un problema específico de WPF. Y lo único acerca de enhebrar en la documentación es la información habitual de "seguridad de hilo", que es la misma para casi todas las clases. Dice * no se garantiza que sea seguro para subprocesos *, no * no puede ser utilizado por varios subprocesos *. No estar seguro de subprocesos no significa que no pueda usar múltiples subprocesos, solo significa que debe manejar la sincronización usted mismo. –

Cuestiones relacionadas