Когда обновлять ViewModel из базы данных [Кэширование ViewModel]

#c# #asp.net-mvc #performance #caching #model

#c# #asp.net-mvc #Производительность #кэширование #Модель

Вопрос:

Хорошо, поэтому я постараюсь сделать вещи короткими и понятными.

Как вы, возможно, знаете, у меня есть моя база данных, использующая EntityFramework, затем у меня есть классы модели базы данных, которые инициализируются базой данных, а затем у меня есть модели представления, в которых у меня есть поля для каждого элемента управления html, в последнем у меня есть контроллер с определенным экземпляром ViewModel.

Мой вопрос в том, что модель представления создается один раз по запросу моего контроллера (любое действие), в других случаях я всегда проверяю, равно ли оно нулю, и если оно равно нулю, тогда я перестраиваю модель представления, извлекая данные из базы данных, используя мои классы моделей базы данных, это правильноправильно? Таким образом, я могу добиться улучшения производительности.. верно? поскольку я повторно использую модель представления и не создаю ее каждый раз …?

Проблема возникает, когда какое-либо поле обновляется администратором в бэк-офисе. Как я могу это преодолеть? Я вижу следующие варианты:

1) Установите время жизни (минуты / часы) для моего объекта ViewModel внутри контроллера (по истечении срока действия я устанавливаю для него значение null).

2) Я пытаюсь обработать CTRLF5комбинацию клавиш и устанавливаю для объекта ViewModel внутри контроллера значение null.

3) Я перестраиваю ViewModel при каждом http-запросе к контроллеру (это так плохо …)

4) Я использую Http-сеанс каждого клиента, когда серверная часть обновляет поле, каждый Http-сеанс на моем ASP.NET WebApplication get запускается с некоторым флагом, чтобы установить для объекта модели представления значение null (я даже не знаю, возможно ли это, но это кажется самым элегантным способом, не так ли?

Вот пример того, что я делаю в данный момент, но в некоторых случаях мне может потребоваться воссоздать ViewModel (поскольку база данных для полей представления изменилась):

     [Authorize]
    public class HomeController : Controller
    {
        private IndexViewModel indexModel;

        [Authorize]
        public ActionResult Index(IndexViewModel model, string lang = "en")
        {
            indexModel = model;
            if (indexModel == null)
                indexModel = new IndexViewModel();

            indexModel.SelectedLanguage = lang;

            return View(indexModel);
        }

       //more actions..
}
  

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

Спасибо!

РЕДАКТИРОВАТЬ: вопрос отредактирован с дополнительной информацией.

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

1. Что вы имеете в виду в других случаях, когда я всегда проверяю, равно ли оно нулю ? Сохраняете ли вы модель представления в Session (и почему?). И что заставляет вас думать, что инициализация вашей модели представления при каждом запросе плоха?

2. Привет @StephenMuecke спасибо за ваш ответ. Я имею в виду, что я делаю что-то вроде проверки того, что модель равна нулю, в этом случае я снова создаю модель, вы понимаете? Я все равно не сохраняю модель, модель просто продолжает переходить от представления контроллера к view-controller, я получаю модель в параметрах моего метода действия. Я говорю, что инициализация моей модели представления плоха, потому что я буду использовать процессор в тех случаях, когда данные вообще не изменились… поэтому я мог бы использовать те же поля, которые уже существуют в объекте представления модели…

3. Я понимаю, что вы пытаетесь поддерживать свою модель представления в актуальном состоянии, но вы не хотите запрашивать базу данных при каждом http-запросе, поступающем на контроллер. Это то, что вы имеете в виду?

4. @DarkLink, я бы так не поступил. Если вы хотите сохранить состояние вашей модели представления между запросами к вашему контроллеру, вам лучше сохранить его в Cache объекте и настроить для него политику истечения срока действия. Затем вы можете просто проверить, доступен ли объект в кэше, и, если нет, инициализировать его и обновить из базы данных.

5. Вам нужно будет включить значения всех свойств вашей модели в URL. Но это действительно не имеет смысла, и неясно, что вы пытаетесь сделать с этим кодом. Веб не имеет состояния. Когда вы делаете запрос, создается новый экземпляр вашего контроллера, и значение indexModel всегда будет null . Если вы не передали значения своей модели в URL, то model это просто новый экземпляр IndexViewModel . ТАКИМ образом, вы можете удалить 1-ю строку кода 3 и просто использовать model.SelectedLanguage = lang; return View(model);

Ответ №1:

По умолчанию ASP.NET Контроллеры MVC создаются при каждом запросе. Это означает, что ваша indexModel переменная всегда будет null отображаться в каждом запросе. Веб не имеет состояния, поэтому у вас мало вариантов для хранения информации между запросами.

На стороне клиента

  • Cookie
  • Скрытые поля

На стороне сервера

  • База данных или другое хранилище
  • Сессия
  • Кэш

Насколько я понял, вы используете некоторую базу данных и просто хотите предотвратить отправку запросов в базу данных при каждом запросе для достижения лучшей производительности. Одним из вариантов является использование System.Web.Caching.Cache object . Затем вы можете написать что-то подобное.

 public class HomeController : Controller
{
    [Authorize]
    public ActionResult Index(string lang = "en")
    {
        IndexViewModel indexViewModel;
        if (HttpContext.Cache["IndexViewModel"]!=null) 
        {
            indexViewModel = HttpContext.Cache["IndexViewModel"];
        }
        else 
        {
            // get your index view model from database by calling some service or repository
            indexViewModel = DatabaseService.GetIndexViewModelFromDatabase();
            // once we got the view model from a database we store it to cache and set it up so that it gets expired in 1 minute
            HttpContext.Cache.Insert("IndexViewModel", indexViewModel, null, DateTime.UtcNow.AddMinutes(1), Cache.NoSlidingExpiration);
        }

        indexViewModel.SelectedLanguage = lang;

        return View(indexModel);
    }

   [HttpPost]
   [Authorize(Roles="Backoffice")]
   public ActionResult ResetCache(string cacheKey)
   {
       if (HttpContext.Cache[cacheKey] != null)
           HttpContext.Cache.Remove(cacheKey);
   }
   //more actions..
}
  

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

1. Спасибо за ваш вклад, Алексей! Я искал это, это действительно помогает мне, не могли бы вы просто сказать мне одну вещь? и, может быть, отредактируйте свой ответ своим ответом об этом? Вопрос в следующем: «Может ли сервер, я имею в виду, пользователь с определенной ролью (backoffice) вызвать определенное действие в контроллере, которое запускает установку всего кэша клиента в значение null? Итак, мне не нужно ждать истечения срока действия, и данные немедленно обновляются после следующей проверки объекта модели? Спасибо!

2. Да, это верно, я знаю, что это способ сделать это, мой вопрос в том, удалит ли это кэш для зарегистрированного пользователя, верно? не все просматривают веб-сайт, используя кеш в этот момент, верно? Возможно, это слишком глупо спрашивать и даже невозможно… но чтобы вы поняли, я хотел бы запустить эту операцию (resetcache) для всех, кто просматривает в этот конкретный момент…

3. @DarkLink, согласно документации Cache , для каждого домена приложения создается один экземпляр. Это означает, что это общее для всех ваших пользователей, поэтому, если вы поместите или удалите что-то в / из кэша, это повлияет на всех ваших пользователей. Если ваша viewmodel должна содержать некоторую пользовательскую информацию, вы можете изменить ключ «IndexViewModel», скажем, на «IndexViewModel_xx», где xx — уникальный идентификатор или адрес электронной почты текущего вошедшего в систему пользователя. Это позволит сбросить кэш или настроить его для каждого пользователя индивидуально.

4. Большое вам спасибо @AlexeyAndrushkevich! Это именно то, что я ищу! 🙂