Сначала код EF и кэширование

#ef-code-first

#сначала ef-код

Вопрос:

У меня есть следующий псевдокод, сначала использующий код EF:

 User user = GetFromCache();

Playlist playlist = new Playlist { Name = "name", User = user };

playlistRepository.Add(playlist);

unitOfWork.Commit();
  

Метод GetFromCache() проверяет, находится ли пользователь в кэше, и если нет, он использует репозиторий для получения его из базы данных. Если он находится в кэше, он возвращает его.

Когда я запускаю этот код в первый раз, все хорошо. Когда я запускаю его во второй раз, и он извлекает пользователя из кэша, я получаю исключение: на объект entity не могут ссылаться несколько экземпляров IEntityChangeTracker.

Почему это так?

Ответ №1:

Объекты, созданные контекстом, сохраняют ссылку на этот контекст для отложенной загрузки и отслеживания изменений. Если вы собираетесь кэшировать объект, вы должны удалить ссылку на этот контекст, отсоединив его (в качестве побочного эффекта контекст не будет GCed, пока у объекта нет других ссылок).

Итак, если вы собираетесь кэшировать его, отсоедините его следующим образом

 context.Entry(user).State = EntityState.Detached;
  

Затем внутри вашего GetFromCache() вам нужно прикрепить объект к текущему контексту. В противном случае EF вставит новую запись для пользовательского объекта.

 User GetFromCache()
{
    var user = /* retrieve from cache */
    if (user != null)
    {
        context.Users.Attach(user);
    }
    else
    {
        //get user from database
    }

    return user;    
}
  

Комментарии:

1. Означает ли это, что вам нужно завершить использование объекта, прежде чем вы сможете его кэшировать?