2010-04-04 15 views
7

Entity Framework'teki tembel yükleme işleminin yalnızca ObjectContext'u oluşturan iş parçacığından çalıştığını öğrendim. Sorunu açıklamak için, sadece 2 öğeyi içeren basit bir modelle basit bir test yaptım: Person ve Address. İşte kod:Entity Framework temkinli yükleme işlemi diğer threaddan çalışmıyor

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 yöntem gayet iyi çalışıyor, Address mülkiyet lazily yüklenir. Ancak,numaralı dosyada, p2.Address boş olduğundan p2.Address.City üzerinde bir NullReferenceException olsun.

Bu bir hata mı? Çalışması gereken yol bu mu? Eğer öyleyse, bununla ilgili herhangi bir belge var mı? Konuyla ilgili hiçbir şey bulamadım MSDN veya Google ...

Ve daha önemlisi, bir geçici çözüm var mı? (Diğer açıkça ... çalışan iş parçacığı LoadProperty çağırmaktan daha)

Herhangi bir yardım çok

PS mutluluk duyacağız: VS2010 kullanıyorum, o EF 4,0 yüzden. EF'nin önceki sürümünde aynı olup olmadığını bilmiyorum ...

+1

Motivasyonunuzdan emin değilim, ancak .NET takımı, iş parçacığı havuzunu açık bir şekilde kullanmak yerine Görev ve Eylemle yazılması için cesaret vermeyi amaçlıyor. Belki birisi bunun hakkında iyi bir alıntı yapabilir? –

+0

'p2' kullanımı hakkında biraz bilgi verebilir misiniz? Sanırım hiçbir şey değiştirmedi mi? –

+0

@jarrett: belki, ama sorun değil ... sorun zaten bir iş ile aynı olurdu, çünkü bu zaten konuları kullanır. @Henk: p2 olmadan da çalışmıyor, ama yine de gerekli, aksi halde her lambda aynı değişkeni kapatacaktı; Ayrıntılar için bu makaleye bakın: http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –

cevap

7

Tasarım gereği bu mu? Evet; Yüklü, örtülü veya açık herhangi bir çağrı, sonunda ObjectContext ve ObjectContext is documented to be not thread-safe'dan geçer.

Olası bir geçici çözüm, varlığın çalışan iş parçacığındaki nesne bağlamından ayrılması ve geçerli iş parçacığındaki bir nesne bağlamına iliştirilmesi olabilir.

+0

Cevabınız için teşekkür ederiz. Ne yazık ki, benim durumumda başka bir nesne bağlamı yaratmak kesinlikle aşırı. Ben bir async bağlama kullanarak bir WPF uygulamasında görüntüleri yüklemeye çalışıyorum ve ben gerçekten her görüntü için yeni bir bağlam oluşturmak istemiyorum (şu anda yaklaşık 150 görüntü) –

+0

Ben bu noktada bir WPF sorusu olduğunu düşünüyorum bir EF sorusu değil. EF'in kuralları çok basit. WPF kullanarak onları takip etmek başka bir konudur. –

+0

Eh, bunu WPF'de kullanıyorum, ancak WPF'ye özgü bir sorun değil. Ve belgelerin işlenmesiyle ilgili tek şey, hemen hemen tüm sınıflar için geçerli olan "iplik güvenliği" bilgisidir. * Bu iş parçacığının * güvenli olması garanti edilmez *, değil * Birden fazla iş parçacığı tarafından kullanılamaz *. İş parçacığı güvenli olmamak, çok iş parçacığı kullanamayacağınız anlamına gelmez, yalnızca eşitleme işlemlerini kendiniz halletmeniz gerektiği anlamına gelir. –