Как я могу исправить "Экземпляр ObjectContext был удален" - PullRequest
0 голосов
/ 26 февраля 2020

Я разработал приложение со структурой сущностей. Я получаю

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

иногда возникает ошибка.

Я провел некоторое исследование на inte rnet, но я не мог понять это. Я был бы очень признателен, если бы вы могли помочь

HomeController:

public ActionResult Index()
{
    return View(noteManager.ListQueryable().Where(x => x.IsDraft == false && x.IsApproved == true).OrderByDescending(x => x.ModifiedOn).Take(10).ToList());
}

Моя заметка Entity:

public class Note : MyEntitesBase
{       
    public string Tittle { get; set; }
    public string Text { get; set; }
    public bool IsDraft { get; set; }
    public int LikeCount { get; set; }
    public int CategoryID { get; set; }

    public virtual EvernoteUser Owner { get; set; } 
    public virtual List<Comment> Comments { get; set; } 
    public virtual Category Category { get; set; } 
    public virtual List<Liked> Likes { get; set; } 

    public Note()
    {
        Comments = new List<Comment>();
        Likes = new List<Liked>();
    }

}

Мой комментарий Entity:

public class Comment : MyEntitesBase
{
    public string Text { get; set; }
    public bool CommentStatus { get; set; }

    public virtual Note Note { get; set; }
    public virtual EvernoteUser Owner { get; set; } 
}

My DatabaseContext:

public class DatabaseContext :DbContext 
{
   public DbSet<EvernoteUser> EvernoteUsers { get; set; }
   public DbSet<Note> Notes { get; set; }
   public DbSet<Comment> Comments { get; set; }
   public DbSet<Category> Categories { get; set; }
   public DbSet<Liked> Likes { get; set; }

   public DatabaseContext()
   {           
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<DatabaseContext,Configuration>()); 

    }

}

1 Ответ

1 голос
/ 26 февраля 2020

Эта проблема часто возникает из-за сериализатора, который касается всех свойств сериализуемого объекта для отправки в представление. Если 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...