Аннулирование / отключение кэша Entity Framework

я вижу, что есть множество вопросов о кэше 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 метод следующий

    [HttpPost]
    public ActionResult Index(string[] codice, string[] flagpf, string[] flagpg, string[] flagammbce, string[] flagammdiv, string[] flagammest,
        string[] flagintab, string[] flagfinanz, string[] flagita, string[] flagest, string pNew){
            Sottogruppo2015Manager.ActivateFlagFor("pf", flagpf);
            Sottogruppo2015Manager.ActivateFlagFor("pg", flagpg);
            Sottogruppo2015Manager.ActivateFlagFor("ammbce", flagammbce);
            Sottogruppo2015Manager.ActivateFlagFor("ammdiv", flagammdiv);
            Sottogruppo2015Manager.ActivateFlagFor("ammest", flagammest);
            Sottogruppo2015Manager.ActivateFlagFor("intab", flagintab);
            Sottogruppo2015Manager.ActivateFlagFor("finanz", flagfinanz);
            Sottogruppo2015Manager.ActivateFlagFor("ita", flagita);
            Sottogruppo2015Manager.ActivateFlagFor("est", flagest);

            return RedirectToAction("Index", new { pNew });
 }

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

UPDATE table SET --param1-- = 0;
UPDATE table SET --param1-- = 1 where id in (--param2--)

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

следующее поведение:

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

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

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

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

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

  • я еще не интегрировал весенние транзакции в мои классы менеджера
  • каждый объект, который выполняет действия на базе I<Entity>Manager расширения BaseManager
  • DbContext является объектом Spring с областью запросов. Я уже спросил о размещении объектов с областью запроса но в настоящее время я реализовал обходной путь, который, хотя и плохой,правильно распоряжается из DbContext в конце запроса.

пример кода

public class ExampleManagerImpl : BaseManager, IExampleManager
{
    public void ActivateFlagFor(string aFlag, string[] aList)
    {
        string sql = "UPDATE table SET flag" + aFlag + " = 0";
        RunStatementV1(sql);

        if (aList != null && aList.Any())
        {
            sql = "UPDATE table SET flag" + aFlag + " = 1 WHERE id in (" + aList.ToCsvApex() + ")";
            RunStatementV1(sql);
        }
    }

    public IList<Models.Example> GetAll()
    {
        return DataContext.example.ToList(); //I don't dispose of the DataContext willingly
    }
}

и

public abstract class BaseManager {

    public DbContext DataContext { get; set; } //Autowired

    protected void RunStatementV1(string aSqlStatement)
    {
        IDbConnection connection = DataContext.Database.Connection;
        if (connection.State == ConnectionState.Closed || connection.State == ConnectionState.Broken) connection.Open(); //Needed because sometimes I found the connection closed, even if I don't dispose of it
        using (IDbCommand command = connection.CreateCommand())
        {
            command.CommandText = aSqlStatement;
            command.ExecuteNonQuery();
        }

    }
}

что я пробовал

2 ответов


если вы хотите полностью игнорировать кэш EF6 для извлечения данных, добавьте AsNoTracking() до конца вашего запроса (перед вызовом ToList() или делать что-либо еще, что бы выполнить запрос.

MSDN on AsNoTracking()

обратите внимание, что это не будет проверять кэш для существующих данных, а также не будет добавлять результаты вызова базы данных в кэш. Кроме того Entity Framework не будет автоматически обнаруживать изменения сущностей, которые вы получить из базы данных. Если вы хотите изменить какие-либо объекты и сохранить их обратно в базу данных, перед вызовом SaveChanges().

ваш метод в настоящее время:

public IList<Models.Example> GetAll()
{
    return DataContext.example.ToList();
}

это изменится на:

public IList<Models.Example> GetAll()
{
    return DataContext.example.AsNoTracking().ToList();
}

если вас интересуют другие варианты работы с кэшем EF, я написал сообщение в блоге о переборе кэша EF6.


У меня тоже была эта проблема, но я мог ее исправить.

Я использую шаблон репозитория и использую DI по умолчанию .Net Core. Я использую AddSingleton(...), но это неправильно использовать с DbContext.

Итак, я изменился на AddScoped, как я читал из docs:службы с областью действия создаются один раз для каждого запроса.

это решило мою проблему.

вы должны прочитать этот раздел из ms docs: срок службы и регистрация Опции