Я просто узнал, что ленивая загрузка в Платформе Объекта только работает от потока, который создал ObjectContext
. Для иллюстрирования проблемы я сделал простой тест с простой моделью, содержащей всего 2 объекта: Person
и Address
. Вот код:
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
метод хорошо работает, Address
свойство лениво загружается. Но в TestMultiThread
, Я получаю a NullReferenceException
на p2.Address.City
, потому что p2.Address
является пустым.
Это, что ошибка? Действительно ли это - способ, которым это, как предполагается, работает? Если так, есть ли какая-либо документация, упоминая это? Я ничего не мог найти на предмете на MSDN или Google...
И что еще более важно, там обходное решение? (кроме явного вызова LoadProperty
от рабочего потока...)
Любая справка очень ценилась бы
PS: я использую VS2010, таким образом, это - EF 4.0. Я не знаю, было ли это то же в предыдущей версии EF...
Это задумано? Да; любой вызов Load, неявный или явный, в конечном итоге будет проходить через ObjectContext
, а ObjectContext задокументирован как небезопасный для потоков .
Возможный обходной путь - отсоединить объект от контекста объекта в рабочем потоке и присоединить его к контексту объекта в текущем потоке.