У меня есть сценарий, в котором я буду получать данные с несколькими строками данных (иногда в тысячах), и мне нужно обрабатывать данные построчно. При обработке данных построчно сначала мне нужно вызвать базу данных ONprem sql, где я вызову хранимую процедуру с входными и выходными параметрами, и после выполнения SP мне нужно получить выходные данные и обновить другую таблицу, которая находится в другая база данных SQL Azure в соответствии с выходным параметром.
Проблема в том, что когда я использую USING, я чувствую, что он открывает и закрывает соединение один раз для каждой строки для каждой из двух баз данных, и если есть 1000 строк данных, он может открывать и закрывать DB1 10000 каждый и DB2 1000 каждый, который занимает много времени и обращений к серверу.
Как я могу свести к минимуму это и, возможно, оставить соединение открытым, пока оно не сделает все в цикле foreach.
Ниже приведен пример фрагмента кода:
public void Main()
{
//Declare Variables
int InputID;
string OutputProcessedMsg;
string SqlConn = "Data Source=xyx.com;Initial Catalog=ddddd;Provider=SQLNCLI11.1;Integrated Security=SSPI";
string AzureSqlConn = "Data Source=vvvv.dev.com;Initial Catalog=yyyy;Provider=SQLNCLI11.1;Integrated Security=SSPI";
Object AllData = Dts.Variables["User::VarAllPowerAppData"].Value;
// this gets the data object and sets it to a data table
OleDbDataAdapter A = new OleDbDataAdapter();
System.Data.DataTable dt = new System.Data.DataTable();
A.Fill(dt, AllData);
//DataTable sourceTable = dt;
foreach (DataRow dr in dt.Rows)
{
InputID = Convert.ToInt32(dr[0]);
using (SqlConnection conn = new SqlConnection(SqlConn))
{
using (SqlCommand cmd = new SqlCommand("UpdateDataOnpremSQL", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// set up the parameters and it's values
cmd.Parameters.Add("@ID", SqlDbType.VarChar,15).Value = InputDealerID;
cmd.Parameters.Add("@ProcessedMsg", SqlDbType.VarChar,-1).Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
OutputProcessedMsg = Convert.ToString(cmd.Parameters["@ProcessedMsg"].Value);
conn.Close();
}
}
using (OleDbConnection Oconn = new OleDbConnection(AzureSqlConn))
{
using (OleDbCommand cmd = new OleDbCommand("UpdateDataAzureSQL", Oconn))
{
cmd.CommandType = CommandType.StoredProcedure;
// set up the parameters and it's values
cmd.Parameters.AddWithValue("@ID", SqlDbType.VarChar).Value = InputDealerID;
cmd.Parameters.AddWithValue("@ProcessedMsg", SqlDbType.VarChar).Value = OutputProcessedMsg;
Oconn.Open();
cmd.ExecuteNonQuery();
Oconn.Close();
}
}
}
}
Я пробовал этот пул соединений, но кажется, что для каждой строки он попадет в db, откроет и закроет соединения, которые повлияют на производительность сервера БД, и, следовательно, мне нужно что-то, где соединение будет открыто, и процесс будет быстрее при переключении на БД до конца цикла foreach Databtable
Он делает то, о чем вы его просите. Вы объявляете свои связи внутри цикла foreach
. На каждой итерации он создает новое соединение, открывает его, выполняет команду и закрывает соединение.
Чтобы добиться лучшей производительности, вам следует подумать о создании соединения в вашем блоке Declare Variables
, открыть его после создания, выполнить все команды в вашем цикле и закрыть соединение после завершения цикла.
Вы открываете соединение перед циклом
А потом закрыть их
public void Main()
{
//Declare Variables
int InputID;
string OutputProcessedMsg;
string SqlConn = "Data Source=xyx.com;Initial Catalog=ddddd;Provider=SQLNCLI11.1;Integrated Security=SSPI";
SqlConnection conn = new SqlConnection(SqlConn);
string AzureSqlConn = "Data Source=vvvv.dev.com;Initial Catalog=yyyy;Provider=SQLNCLI11.1;Integrated Security=SSPI";
OleDbConnection Oconn = new OleDbConnection(AzureSqlConn);
Object AllData = Dts.Variables["User::VarAllPowerAppData"].Value;
// open all connections only once
conn.Open();
Oconn.Open();
// this gets the data object and sets it to a data table
OleDbDataAdapter A = new OleDbDataAdapter();
System.Data.DataTable dt = new System.Data.DataTable();
A.Fill(dt, AllData);
//DataTable sourceTable = dt;
foreach (DataRow dr in dt.Rows)
{
InputID = Convert.ToInt32(dr[0]);
using (SqlCommand cmd = new SqlCommand("UpdateDataOnpremSQL", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// set up the parameters and it's values
cmd.Parameters.Add("@ID", SqlDbType.VarChar, 15).Value = InputID;
cmd.Parameters.Add("@ProcessedMsg", SqlDbType.VarChar, -1).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
OutputProcessedMsg = (string)cmd.Parameters["@ProcessedMsg"].Value;
}
using (OleDbCommand cmd = new OleDbCommand("UpdateDataAzureSQL", Oconn))
{
cmd.CommandType = CommandType.StoredProcedure;
// set up the parameters and it's values
cmd.Parameters.AddWithValue("@ID", SqlDbType.VarChar).Value = InputID;
cmd.Parameters.AddWithValue("@ProcessedMsg", SqlDbType.VarChar).Value = OutputProcessedMsg;
cmd.ExecuteNonQuery();
}
}
conn.Close();
Oconn.Close();
}