Как безопасно и эффективно кэшировать команды ADO.NET?

Я хочу использовать этот паттерн:

SqlCommand com = new SqlCommand(sql, con);
com.CommandType = CommandType.StoredProcedure;//um
com.CommandTimeout = 120;
//com.Connection = con;  //EDIT: per suggestions below

SqlParameter par;
par = new SqlParameter("@id", SqlDbType.Int);
par.Direction = ParameterDirection.Input;

com.Parameters.Add(par);

HttpContext.Current.Cache["mycommand"] = com;

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

И клонирование команды, взятой из кеша, вероятно, дороже, чем создание новой команды с нуля.

Насколько потокобезопасен кэш ASP.NET? Не упускаю ли я других потенциальных ловушек? Будет ли этот метод работать для команд без параметров, несмотря на проблемы с потоками?

Осветление: Если я хочу образно прострелить себе ногу, как мне прицелиться? Есть ли способ заблокировать доступ к объектам в кеше, чтобы доступ был сериализован?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
2 190
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Самым важным в этом сценарии является кеширование соединения, которое выполняется за вас, и вы не должны пытаться следить за этим самостоятельно.

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

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

Очень просто: не надо. Если вы не видите, что это неправильно, вам нужно больше узнать об ADO.NET. Существует множество литературы, в которой объясняется, как это правильно делать: просто создавайте соединения и команды, когда они вам нужны, и убедитесь, что вы их правильно разместили.

Как утверждали другие, это просто плохая идея. Это плохая идея по ряду причин.

Более того, если вы находитесь в ситуации высокой нагрузки, сохранение команды для каждого пользователя действительно быстро заполнит кеш и, в зависимости от приоритетов и т. д., Начнет вызывать выпадение других элементов из кеша. , это ДЕЙСТВИТЕЛЬНО должно быть там.

В ADO.NET вы действительно должны создавать, использовать, а затем удалять свои команды и соединения по мере их использования. Что касается производительности, мне НИКОГДА не приходилось менять эту систему ... и я не слышал о многих других, которые тоже меняли.

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

Зачем вам вообще кэшировать команда? Накладные расходы на создание команды незначительны - вы просто создаете новую пару объектов и устанавливаете некоторые свойства. Я никогда не видел, чтобы это было узким местом ..

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

Кэшируйте свои результаты и создавайте соединение (и команду) только в том случае, если кэш результатов равен нулю:

PsuedoCode:

result = getResultFromCache(CacheKey)
if (result == null)
{
     result = getResultFromDB();
     InsertIntoCache(result,cacheKey);
}

return result;
Ответ принят как подходящий

Мне следовало спросить, как заблокировать элемент в кеше ASP.NET, вместо того, чтобы говорить, что я собирался поместить в кеш.

lock(Cache)
  {
    // do something with cache that otherwise wouldn't be threadsafe
  }

Ссылка: http://www.codeguru.com/csharp/.net/net_asp/article.php/c5363

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

Joe 02.03.2018 11:06

Другие вопросы по теме