Entity framework отключить кэширование

Обновлено: 05.07.2024

Я получил некоторые значения в моей базе данных, используя EF. Возвращает отлично, а значения отображаются в метках. Но когда я удаляю все значения в моей таблице (без использования EF), запрос EF возвращает мои старые значения. Я знаю, что EF хранит значения в кэше и возвращает кэшированные данные для последующих запусков. Это правильно?

Итак, как я могу решить проблему, когда я удалил все значения в моей базе данных, но EF возвращает старые значения?

Edit

Теперь я использовал datamodel.SaveChanges() . Но теперь он возвращает те же старые значения.

Мой пример запроса выглядит следующим образом:

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

Если кажется, что это будет обычное явление, вам следует отключить кеширование объектов в своих запросах:

или для отключения кэширования на уровне объекта для конкретной сущности,

Когда вы используете EF, он по умолчанию загружает каждую сущность только один раз для контекста. Первый запрос создает объект сущности и сохраняет его внутри. любой следующий запрос, который требует сущность с тем же ключом, возвращает это сохраненный экземпляр. Если значения в хранилище данных изменились, вы все равно получите объект со значениями из исходного запроса

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

Вы загрузили список, этот список является вашим кешем в памяти. Даже вызов Save Changes не обновится. Вам придется запросить контекст еще раз, то есть создать новый список.

Чтобы увидеть изменения, вам нужно будет выполнить следующую строку еще раз,

Я думаю, что вы должны следовать некоторым другим решениям здесь, но кажется, что вы хотите очистить кеш. Вы можете добиться этого, выполнив следующие действия:

Приведенный ниже код помог обновить мой объект новыми значениями базы данных. Команда Entry (object) .Reload () заставляет объект вызывать значения базы данных

Я рекомендую вам использовать некоторые MergeOption для всех EntitieSet после создания контекста, например:

Но, если вы хотите очистить «кэшированные» сущности, отсоединив их.

Где Ctx - мой контекст.

Во-первых, я бы не предлагал изменять внешнюю по отношению к вашей системе базу данных, если только вы не занимаетесь тестированием и разработкой.

EF DbContext содержит интерфейс IDisposable. Чтобы освободить любые кэшированные данные, либо выполните вызовы Dispose вручную, либо поместите объект базы данных в блок using.

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

При работе с веб-приложениями используйте экземпляр контекста для запрос.

Если вы используете MVC, вы можете использовать шаблон Dispose в вашем контроллере следующим образом:

Но вам действительно стоит взглянуть на внедрение зависимости в управлять временем жизни DbContext

Я думаю, что вам нужно GetDatabaseValues() . Используется как:

Информация ниже представлена ​​от msdn :

Текущие значения - это значения, которые свойства объекта в настоящее время содержат. Исходные значения - это значения, которые были прочитаны из базы данных, когда объект был запрошен. Значения базы данных значения в том виде, в котором они в данный момент хранятся в базе данных. Получение значения базы данных полезны, когда значения в базе данных могут иметь изменилось, так как объект был запрошен, например, при одновременном редактировании база данных была создана другим пользователем.

я вижу, что есть множество вопросов о кэше EF, но я еще не нашел решения своей проблемы.

прямой вопрос

как полностью отключить кэш Entity Framework 6? Или я могу программно сказать EF забыть о кэше, потому что что-то случилось с данными?

во-первых, у меня есть унаследовала приложение, сделанное из странной смеси EF (model-first для определения сущностей) и простой старый SQL (для управления данными). То, что я сделал, это рефакторинг приложения для того, чтобы:

  • сделать простые запросы (например, GetAll() для сущности) используйте EF6 LINQ
  • оставьте сложные манипуляции с данными в SQL, используя DbContext.Database.Connection при необходимости
  • добавить Spring.Web поддержка включения DI и транзакций (еще нет)

в текущий момент я реорганизовал код так, чтобы основная функция приложения (запуск сложного SQL запросы к огромным наборам данных) работает так же, как и раньше, но затем поиск доменных сущностей выполняется умнее, используя а всего Entity Framework, насколько это возможно

как большинство.

вот как выглядит страница

enter image description here

в основном Controller метод следующий

каждого string[] параметр представляет собой столбец в таблице. The ActivateFlagFor метод выполняет два запроса в последовательности

когда кэш срабатывает

  • я сначала загружаю страницу, выдающую LINQ select: проверки совпадают с единицами и нулями в колонки
  • я меняю один или несколько чеков и отправляю
  • контроллер выдает запросы на обновление проверок в DB
  • до перенаправления (!значит новый запрос!) чтобы перезагрузить страницу, Я проверяю БД и изменения применяются
  • страница перезагружается, выдавая тот же LINQ select выше:отображаются старые чеки

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

я понимаю, что кэширование EF-отличная функция для производительности, но в моем случае я просто не хочу этого, по крайней мере, пока я не перенесу все приложение на LINQ DML (вероятно, невозможно).

как я использую DbContext

конечно, некоторые из вас могут спросить: "как вы использовать DbContext можно?- вы правильно распорядились?".

Модель для этого контекста затем кэшируется и предназначена для всех остальных экземпляров контекста в домене приложения. Это кэширование можно отключить, установив свойство ModelCaching на данный ModelBuidler, но обратите внимание, что это может серьезно ухудшить производительность.

Проблема заключается в том, что модельный конструктор не содержит никакого свойства с именем ModelCaching.

Как можно отключить кэширование модели (например, для изменения конфигурации модели во время выполнения)?

ОТВЕТЫ

Ответ 1

См. также конструктор DbContext для передачи в модели DbContext Constructor

Я не пробовал, но теоретически вы можете проходить в модели каждый раз.

Ответ 2

Предупреждение о переходе: само собой разумеется, что приведенный ниже механизм будет охватывать ваши потребности, если вам не нужно выполнять объединения между таблицами, которые поступают из разных контекстов. Если вам нужны такие операции, вам придется дополнительно уточнить механизм, показанный ниже, с помощью небольшого API, чтобы вы могли динамически связывать указанные таблицы с некоторой строкой или номером (чтобы вы могли динамически получать и комбинировать свои соответствующие DBS файлы во время выполнения), Выполнение такого рода -больше общего - немного сложное и выходит за рамки этого ответа.

Здесь полномасштабная реализация механизма, выдвинутого байрогом, - все это относится к нему. Обратите внимание, что мы получаем подключение к базе данных через новый DbContext по причинам, объясняемым в комментариях:

Ответ 3

Здесь похож вопрос

Единственный доступный подход исходит от диспетчера программ команды Entity Framework (Rowan Miller (MSFT)):

Я пробовал следующий подход:

В результате я смог изменить параметры DbCompiledModel каждый раз, когда я вызываю конструктор DbContext. Это все, что мне нужно.

Ответ 4

У меня такая же проблема: один контекст db, 2 или более разные модели db (только по именам таблиц)

Мое решение для EF6: все еще можно использовать внутреннее кэширование структуры Entity Framework модели db, но сделать дифференциацию между DbModel (s) в одном и том же DbContext, реализовав IDbModelCacheKeyProvider Interface в производном DbContext.

Внедрите этот интерфейс в свой контекст, чтобы использовать пользовательскую логику для вычисления ключа, используемого для поиска уже созданной модели в кеше. Этот интерфейс позволяет вам иметь один тип контекста, который может использоваться с разными моделями в одном и том же приложении AppDomain или с несколькими типами контекстов, которые используют одну и ту же модель.

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

MemoryCache в ASP.NET Core

Вначале добавим в проект в папку Models новый класс User , который будет описывать используемые данные:

Для взаимодействия с MS SQL Server через Entity Framework добавим в проект через Nuget пакет Microsoft.EntityFrameworkCore.SqlServer . А затем добавим в папку Models класс контекста данных ApplicationContext :

Для взаимодействия с контекстом и бд создадим специальный сервис. Для этого вначале добавим в проект папку Services и в ней определим новый класс UserService :

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

Через встроенный механизм внедрения зависимостей в конструкторе мы можем получить объект кэша IMemoryCache. Применяя методы интефейса IMemoryCache, мы можем управлять кэшем:

bool TryGetValue(object key, out object value) : пытаемся получить элемент по ключу key. При успешном получении параметр value заполняется полученным элементом, а метод возвращает true

object Get(object key) : дополнительный метод расширения, который получает по ключу key элемент и возвращает его

void Remove(object key) : удаляет из кэша элемент по ключу key

object Set(object key, object value, MemoryCacheEntryOptions options) : добавляет в кэш элемент с ключом key и значением value, применяя опции кэширования MemoryCacheEntryOptions

По сути встроенная реализация интерфейса IMemoryCache - класс MemoryCache, который используется по умолчанию, инкапсулирует все объекты кэша в виде словаря Dictionary.

Здесь же кэширование реализуется в двух случаях: при получение объекта по id из бд и при добавлении этого объекта.

При добавлении объект вначале добавляется в базу данных, и в случае удачного добавления, также добавляется в кэш:

При сохранении объекта в кэше в качестве его ключа выступает значение свойства Id.

С помощью параметра AbsoluteExpirationRelativeToNow здесь устанавливатся время кэширования - 5 минут.

При получении объекта по id вначале пытаемся найти этот объект в кэше, и если там не оказалось, то извлеаем его и бд и затем добавляем в кэш.

Если ключ в кэше был найден, то в объект user передается извлекаемое из кэша значение, а метод TryGetValue() возвращает true. Для установки времени кэширования здесь применяется альтернативный способ - метод SetAbsoluteExpiration, который в данном случае таже устанавливает 5 минут.

В итоге у нас получится следующая структура проекта:

Кэширование в ASP.NET Core

Затем нам надо зарегистрировать сервисы кэширования и entity framework и применить компонент middleware в классе Startup :

Прежде всего для добавления возможности кэширования нам надо добавить сервис в методе ConfigureServices() :

По сути этот сервис устанавливает зависимость для IMemoryCache, создавая объект синглтон:

И в классе контроллера HomeController определим следующий код:

В итоге при первом обращении к приложению данные будут извлекаться из базы данных и сохраняться в кэш. При всех последующих обращениях в пределах времени кэширования (в данном случае в течение 5 минут) данные будут извлекаться из кэша:

Читайте также: