#c# #.net #sql #sql-server
#c# #.net #sql #sql-сервер
Вопрос:
У меня есть давно работающая служба с несколькими потоками, вызывающими следующий метод сотни раз в секунду:
void TheMethod()
{
using (var c = new SqlConnection("..."))
{
c.Open();
var ret1 = PrepareAndExecuteStatement1(c, args1);
// some code
var ret2 = PrepareAndExecuteStatement2(c, args2);
// more code
}
}
PrepareAndExecuteStatement — это что-то вроде этого:
void PrepareAndExecuteStatement*(SqlConnection c, args)
{
var cmd = new SqlCommand("query", c);
cmd.Parameters.Add("@param", type);
cmd.Prepare();
cmd.Parameters["@param"] = args;
return cmd.execute().read().etc();
}
Я хочу повторно использовать подготовленные инструкции, подготавливая один раз для каждого соединения и выполняя их до разрыва соединения. Я надеюсь, что это улучшит производительность.
Могу ли я использовать встроенный пул подключений для достижения этой цели? В идеале каждый раз, когда устанавливается новое соединение, все инструкции должны подготавливаться автоматически, и мне нужно иметь доступ к объектам SqlCommand этих инструкций.
Комментарии:
1. Я не понимаю, что вы подразумеваете под «пока соединение не разорвется» и что именно должно происходить между вызовами разных подготовленных инструкций.
2. Все зависит от того, что
// some code
есть!3. Если кто-то перезапустит SQL Server, существующее соединение разорвется.
4. В «некотором коде» я обрабатываю результаты инструкций.
5. Каков размер результирующего набора? Возможно, вы захотите использовать SqlDataReader, если это набор результатов меньшего размера. Кроме того, пул подключений включен по умолчанию. Когда вы открываете () или закрываете () соединение, вы просто получаете доступ из пула или возвращаетесь в него.
Ответ №1:
Предлагаю использовать слегка измененный подход. Немедленно закройте ваше соединение после использования. Вы, безусловно, можете повторно использовать свой SqlConnection.
Работа, выполняемая на //some code
, может занять много времени. Взаимодействуете ли вы с другими сетевыми ресурсами, дисковыми ресурсами или тратите какое-либо количество времени на вычисления? Может ли вам когда-нибудь в будущем понадобиться это сделать? Возможно, интервалы между выполнением инструкции настолько велики, что вы захотите повторно открыть это соединение. В любом случае, соединение должно быть открыто позже и закрыто раньше.
using (var c = new SqlConnection("..."))
{
c.Open();
PrepareAndExecuteStatement1(c, args);
c.Close();
// some code
c.Open();
PrepareAndExecuteStatement2(c, args);
c.Close();
// more code
}
Открывайте поздно, закрывайте рано как журнал MSDN Джона Папы.
Очевидно, что теперь мы имеем здесь кучу дублирующегося кода. Рассмотрите возможность рефакторинга вашего Prepare...()
метода для выполнения операций открытия и закрытия.
Возможно, вы бы рассмотрели что-то вроде этого:
using (var c = new SqlConnection("..."))
{
var cmd1 = PrepareAndCreateCommand(c, args);
// some code
var cmd2 = PrepareAndCreateCommand(c, args);
c.Open();
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();
c.Close();
// more code
}
Комментарии:
1. Возможно, я не понял ваш ответ, но я думаю, что это не решает мою проблему. По вашему предложению я продолжу подготовку инструкции (создание объекта SqlCommand, установка строки запроса, определение типа каждого параметра, вызов . Подготовьте(), установив переменную и выполнив запрос. Я хочу просто установить переменные и выполнить ранее подготовленные инструкции внутри theMethod().
2. @lzm: Вы на самом деле делаете это правильно или в соответствии с рекомендациями. Создайте новую SqlCommand для каждого.
3. Разве подготовленные инструкции не должны готовиться один раз и выполняться много раз?