Эта проблема часто возникает из-за сериализатора, который касается всех свойств сериализуемого объекта для отправки в представление. Если DbContext, с которым был связан объект, удаляется, сериализатор ударит его при попытке выполнить запросы для загрузки связанных деталей.
Быстрое исправление, если noteManager.ListQueryable()
возвращает IQueryable<Note>
, будет:
return View(noteManager.ListQueryable()
.Include(x => x.Owner)
.Include(x => x.Comments)
.Include(x => x.Category)
.Include(x => x.Likes)
.Where(x => x.IsDraft == false && x.IsApproved == true)
.OrderByDescending(x => x.ModifiedOn)
.Take(10).ToList());
Это приложение загружает связанные объекты вместе с примечаниями. Разница между активной загрузкой и отложенной загрузкой заключается в том, что при активной загрузке EF сгенерирует SQL, чтобы объединить все связанные таблицы и затем извлечь связанные строки для до 10 выбранных строк. При отложенной загрузке у вас может быть 10 строк заметок, например, ID 1-10, но при касании каждого свойства EF будет генерировать запросы, такие как:
SELECT * FROM Owners WHERE OwnerID = 22
- идентификатор владельца в заметке 1
SELECT * FROM Comments WHERE NoteId = 1
SELECT * FROM Categories WHERE CategoryId = 4
Идентификатор категории в примечании 1
SELECT * FROM Likes WHERE NoteId = 1
Затем повторите это еще 9 раз, по одному разу для каждой возвращенной строки примечания. Это много запросов, которые EF и DB должны согласовать, пока прокси-сервер сущности содержит слабую ссылку на DbContext. Если запрос удаляет DbContext до того, как сериализатор завершает работу с сущностью, вам передается исключение для обработки паром.
Однако даже при энергичной загрузке это может быть кроличьей ношей, если у какой-либо из этих связанных сущностей есть дочерние сущности. Существует также влияние производительности / ресурсов на загрузку всех связанных данных, которые, вероятно, не понадобятся вашему представлению.
Лучшее долгосрочное решение состоит в том, чтобы определить сериализуемые ViewModel для представления структуры данных, которую фактически должен отображать ваш вид, а затем использовать Select
или Automapper ProjectTo
для заполнения этой модели представления данными из структуры сущностей. Это исключает необходимость загружать данные, просто Select
от структуры, и EF сработает SQL. Это также устраняет риск отложенных загрузок в сериализаторе при условии, что вы Select
полей от сущностей, а не самих сущностей. Это также может значительно уменьшить объем памяти, необходимый серверу и клиенту для хранения данных по запросу, и размер передаваемых данных.
Передача моделей вида в представление означает передачу того же самого или различных моделей представления назад. на сервер, вместо того, чтобы пытаться передать обратно объекты, присоединить и сохранить ... Это выглядит как дополнительная работа и экономия времени по сравнению с повторной загрузкой данных и копированием значений. Однако это намного безопаснее, поскольку вы не рискуете устаревшими, неполными или потенциально подделанными данными, перезаписывая ваши реальные данные. Вы должны всегда перезагружать объекты при выполнении обновления в любом случае, чтобы проверить и убедиться, что строки не были изменены с момента их отправки клиенту. Не верьте ничему, что исходит от веб-клиента. Копирование полей в только что загруженную сущность также означает более эффективные операторы UPDATE
, такие как Attaching + EntityState.Modified или использование DbContext.Update()
, что приводит к операторам обновления, которые обновляют все поля по сравнению с копией, только значения, которые изменения будут добавлены в оператор UPDATE.