Je viens de découvrir que le chargement paresseux dans Entity Framework fonctionne uniquement à partir du thread qui a créé le ObjectContext
. Pour illustrer le problème, j'ai fait un test simple, avec un modèle simple contenant seulement 2 entités: Person
et Address
. Voici le code:Entity Framework chargement paresseux ne fonctionne pas à partir d'un autre thread
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);
});
}
}
}
La méthode TestSingleThread
fonctionne très bien, la propriété Address
est chargé paresseusement. Mais dans TestMultiThread
, j'obtiens un NullReferenceException
sur p2.Address.City
, parce que p2.Address
est nul.
C'est un bug? Est-ce la façon dont il est censé fonctionner? Si oui, y a-t-il des documents qui le mentionnent? Je ne pouvais pas trouver quelque chose sur le sujet sur MSDN ou Google ...
Et plus important encore, existe-t-il une solution de contournement? (Autre que d'appeler explicitement LoadProperty
du thread de travail ...)
Toute aide serait très apprécié
PS: J'utilise VS2010, il est donc EF 4.0. Je ne sais pas si c'était la même chose dans la version précédente de EF ...
Je ne suis pas sûr de votre motivation, mais l'équipe .NET semble encourager le code à être écrit avec Tâche et Action au lieu de faire une utilisation explicite du pool de threads. Peut-être que quelqu'un peut fournir une bonne citation de cela? –
Pouvez-vous élaborer un peu sur l'utilisation de 'p2'? Je suppose que ça n'a rien changé? –
@jarrett: peut-être, mais ce n'est pas le point ... le problème aurait été le même avec une tâche, puisqu'elle utilise des threads quand même. @Henk: ça ne marche pas non plus sans 'p2', mais de toute façon c'est nécessaire, sinon chaque lambda se referme sur la même variable; voir cet article pour plus de détails: http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –