2016-01-04 5 views
4

Я провел 2 дня, пробивая себе голову против этой проблемы, и я не могу ее взломать (проблема такая). Тот же код работал нормально, пока я не добавил отношения с базой данных, и с тех пор я прочитал лот о ленивой загрузке.Eager-loading с использованием LINQ to SQL с Include()

У меня есть две таблицы базы данных с соотношением 1: 1 между ними. PromoCode, и имеет столбец PK с именем id. CustomerPromo стол имеет столбец PromoId, который связан с таблицей PromoCodeid. Эти две таблицы не имеют других отношений. Я создал все это в SQL Server Management Studio, а затем сгенерировал модель из базы данных.

Чтобы сделать несколько сложнее, я делаю это внутри службы данных WCF, но я не считаю, что это должно иметь значение (оно работало до добавления связей базы данных). После включения ведения журнала я всегда получаю исключение в файле журнала с текстом:

Доступ к DataContext после удаления.

Моя функция в настоящее время возвращает все записи из таблицы:

using (MsSqlDataContext db = new MsSqlDataContext()) 
{ 
    // This causes issues with lazy-loading 
    return db.PromoCodes.ToArray(); 
} 

Я прочитал множество статей/страниц/ответы, и все они говорят, чтобы использовать метод .Include(). Но это не работает для меня:

return db.PromoCodes.Include(x => x.CustomerPromos).ToArray(); 

Я попробовал «волшебная строка» версии, а также:

return db.PromoCodes.Include("CustomerPromos").ToArray(); 

Единственный код, который я сумел добраться до работы заключается в следующем:

PromoCode[] toReturn = db.PromoCodes.ToArray(); 

foreach (var p in toReturn) 
    p.CustomerPromos.Load(); 

return toReturn; 

Я попытался добавлялось .Where() критерии в запросе, я попытался .Select(), я пытался двигать .Include() после того, как .Where() (this answer сек ays, чтобы сделать это последнее, но я думаю, что это связано только с вложенными запросами). Я читал о сценариях, где .Include()will silently fail, и после всего этого я не ближе.

Что мне не хватает? Синтаксическая проблема? Логическая проблема? Как только я получаю этот «простой» случай работы, мне также нужно иметь вложенный Include s (т. Е. Если таблица CustomerPromo имела отношение к Customer).

Редактировать
Включая всех соответствующего кода. Остальное - либо LINQ to SQL, либо конфигурация служб данных WCF. Это все есть:

[WebGet] 
[OperationContract] 
public PromoCode[] Test() 
{ 
    using (MsSqlDataContext db = new MsSqlDataContext()) 
    { 
     return db.PromoCodes.Include(x => x.CustomerPromos).ToArray(); 
    } 
} 

Если я позвоню, что через браузер напрямую (например http://<address>:<port>/DataService.svc/Test) я получаю сообщение о соединении сброса и должен искать журналы WCF, чтобы выяснить, «DataContext accessed after Dispose.». Если я сделаю тот же запрос через вызов AJAX на веб-странице, я получаю ошибку AJAX со статусом error (вот и все!).

+0

Можете ли вы поделиться фрагментом кода, который выдает фактическое исключение? Основываясь на том, что у вас есть, это произойдет после того, как вы вернете список «PromoCodes» и затем что-то с ними делаете. –

+0

Если это так, то это потому, что оно находится в службе данных WCF. Он превращается в JSON. В файле журнала есть трассировка стека исключений _massive_, но единственной распознаваемой частью является «WriteArrayOfPromoCodeToJson», «WritePromoCodeToJson», «WriteArrayOfCustomerPromoToJson». – Ian

+0

Единственное, что приходит в голову с тем, что вы использовали до сих пор, это то, что вы пытаетесь использовать свой datacontext вне вашего блока использования. – Niklas

ответ

2

Я преждевременно опубликовал предыдущий ответ, когда у меня не было никаких дочерних данных для извлечения. В то время меня интересовали только выборка родительских данных и работало that answer.

Теперь, когда мне действительно нужны данные для детей, я считаю, что он не работает полностью. Я нашел this article, который указывает, что .Include() (он говорит Including(), но я не уверен, что это опечатка) был удален, и правильным решением является использование DataLoadOptions. Кроме того, мне также понадобилось enable Unidirectional Serialisation.

И для этого мне больше не нужен DeferredLoadingEnabled. Так что теперь окончательный код выглядит следующим образом:

using (MsSqlDataContext db = new MsSqlDataContext()) 
{ 
    DataLoadOptions options = new DataLoadOptions(); 
    options.LoadWith<PromoCode>(p => p.CustomerPromos); 
    db.LoadOptions = options; 

    return db.PromoCodes.ToArray(); 
} 

После установки Unidirectional Serialisation он счастливо возвращает родительский объект без необходимости загружать ребенка или явно установить DeferredLoadingEnabled = false;.

1

Редактировать: Это не решило проблему полностью. Во время тестирования не было никаких дочерних данных, и я не пытался его использовать. Это позволило мне вернуть объект parent, он не возвращает дочерние объекты. Для полного решения см. this answer.

Вопреки всему, что я прочитал, ответ заключается не в использовании .Include(), а в изменении параметров контекста.

using (MsSqlDataContext db = new MsSqlDataContext()) 
{ 
    db.DeferredLoadingEnabled = false; // THIS makes all the difference 
    return db.PromoCodes.ToArray(); 
} 

This link размещены в комментариях вопрос (спасибо @Virgil) намек на ответ. Однако я не смог найти способ получить доступ к LazyLoadingEnabled для LINQ to SQL (я подозреваю, что это для EntityFramework). This page указал, что решение для LINQ to SQL было DeferredLoadingEnabled.

Вот ссылка на документацию MSDN по адресу DeferredLoadingEnabled.

Смежные вопросы