Вопрос

Я строю 4 многослойных веб-приложения ASP.NET. Слои:

  1. Слой данных
  2. Слой объекта
  3. Бизнес-слой
  4. Слой интерфейса

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

Мой слой данных имеет класс под названием SeasplekeyRepository, который имеет функцию, подобную так:

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;
    }
}

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

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

Я уверен, что это потому, что мой DataModelcontainer «DMC» был утилизирован. Как я могу вернуть этот IENumerable объект из моего слоя данных, чтобы он не полагался на ObjectContext, а исключительно на DataModel?

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

Это было полезно?

Решение

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

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

return query.ToList();

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

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

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

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

Другие советы

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

return query.AsEnumerable();

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

Не используйте

return query.AsEnumerable();

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

return query.ToArray();

до утилизации вашего контекста.

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

На мой взгляд, этот сценарий не имеет отношения к асфальтированному () или ASKHEREable (). Попробуй это;

 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
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top