ASP.Net Entity Framework, ошибка объектного контекста - PullRequest
11 голосов
/ 21 мая 2010

Я создаю четырехслойное веб-приложение ASP.Net. Слои:

  1. Уровень данных
  2. Слой сущности
  3. Бизнес-уровень
  4. UI Layer

Слой сущности имеет мои классы модели данных и построен из моей модели данных сущности (файл edmx) в слое данных с использованием шаблонов T4 (POCO). На слой сущностей ссылаются во всех других слоях.

В моем слое данных есть класс с именем SourceKeyRepository, который имеет такую ​​функцию:

public IEnumerable<SourceKey> Get(SourceKey sk)
{
    using (dmc = new DataModelContainer())
    {
        var query = from SourceKey in dmc.SourceKeys
                    select SourceKey;

        if (sk.sourceKey1 != null)
        {
            query = from SourceKey in query
                    where SourceKey.sourceKey1 == sk.sourceKey1
                    select SourceKey;
        }

        return query;
    }
}

Ленивая загрузка отключена, так как я не хочу, чтобы мои запросы выполнялись на других уровнях этого приложения. Я получаю следующую ошибку при попытке доступа к информации на уровне пользовательского интерфейса:

Экземпляр ObjectContext был распоряжаться и больше не может быть использован для операции, требующие подключения.

Я уверен, что это потому, что мой DataModelContainer "dmc" был удален. Как я могу вернуть этот объект IEnumerable из моего уровня данных, чтобы он не полагался на ObjectContext, а исключительно на DataModel?

Есть ли способ ограничить отложенную загрузку только для слоя данных?

Ответы [ 4 ]

18 голосов
/ 21 мая 2010

query вычисляется лениво, поэтому данные не извлекаются из базы данных, пока вы не перечислите их.

Если вы делаете:

return query.ToList();

вы принудительно выполните запрос и избежите проблемы.

Вы получаете сообщение об ошибке, потому что, когда вызывающий объект перечисляет коллекцию, ObjectContext (dmc) уже удаляется благодаря предложению using (что хорошо - избавьтесь от ресурсов, связанных с базой данных раньше!)

Редактировать

В оригинальном посте я использовал AsEnumerable(), который, на мой взгляд, был правильным - до тех пор, пока я сам не попытался использовать его в этой конкретной ситуации. AsEnumerable() только выполняет преобразование типов во время компиляции - оно не перечисляет. Для принудительного перечисления запроса его необходимо сохранить в List или другой коллекции.

5 голосов
/ 10 апреля 2011

Не использовать

return query.AsEnumerable();

использование

return query.ToArray();

перед удалением вашего контекста.

Возврат AsEnumerable не будет выполнять foreach, пока на объект не будет сделана ссылка. Преобразование его в массив гарантирует, что foreach будет выполнен до удаления вашего объекта. Затем вы можете поместить свой контекст в блок использования (что-то, что вы должны сделать).

5 голосов
/ 21 мая 2010

Вы можете вызвать некоторый метод для объекта query, например

return query.AsEnumerable();

Это должно гарантировать, что вы выполните запрос, и, следовательно, вам не понадобится контекст объекта позже.

2 голосов
/ 26 октября 2010

По моему мнению, этот сценарий не имеет отношения к AsEnumerable () или AsQueryable (). Попробуйте это;

 public IEnumerable<SourceKey> Get(SourceKey sk, DataModelContainer dmc) {    

    var query = from SourceKey in dmc.SourceKeys
                select SourceKey;

    if (sk.sourceKey1 != null)
    {
        query = from SourceKey in query
                where SourceKey.sourceKey1 == sk.sourceKey1
                select SourceKey;
    }

    return query;

}

И вы должны получить это свойство с

using (dmc = new DataModelContainer()) {
 // GET
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...