ASP.NET Entity Framework, ObjectContext Error
-
04-10-2019 - |
Вопрос
Я строю 4 многослойных веб-приложения ASP.NET. Слои:
- Слой данных
- Слой объекта
- Бизнес-слой
- Слой интерфейса
Слой объекта имеет свои классы модели данных и создают из моделей данных 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
}