Я ищу подходящий способ обработки нескольких запросов к базе данных, которые, вероятно, выиграют от одновременного запуска. Запросы - это просто хранимые процедуры, которые либо делают вставки, либо слияния, используя данные, которые программно собраны в DataTables в моем приложении ASP.NET MVC.Как правильно выполнять асинхронные/параллельные вызовы базы данных
Конечно, я видел некоторую информацию о async
и await
, и это похоже на то, что мне нужно будет сделать, но у меня нет четкого понимания того, как его реализовать. Некоторая информация говорит о том, что вызовы будут по-прежнему последовательными, и что они все еще будут ждать по другому. Это кажется бессмысленным.
В конечном счете, я хотел бы получить решение, позволяющее запускать все запросы за время, необходимое для выполнения самой длинной процедуры. Я хотел бы, чтобы все запросы возвращали количество затронутых записей (как и сейчас).
Вот что я собираюсь сейчас (это ни в коей мере параллельно):
// Variable for number of records affected
var recordedStatistics = new Dictionary<string, int>();
// Connect to the database and run the update procedure
using (var dbc = new SqlConnection(db.Database.Connection.ConnectionString))
{
dbc.Open();
// Merge One procedure
using (SqlCommand cmd = new SqlCommand("MergeOneProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeOneDataTable);
// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeOne", cmd.ExecuteNonQuery());
}
// Merge Two procedure
using (SqlCommand cmd = new SqlCommand("MergeTwoProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeTwoDataTable);
// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeTwo", cmd.ExecuteNonQuery());
}
// Merge Three procedure
using (SqlCommand cmd = new SqlCommand("MergeThreeProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeThreeDataTable);
// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeThree", cmd.ExecuteNonQuery());
}
// Merge Four procedure
using (SqlCommand cmd = new SqlCommand("MergeFourProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeFourDataTable);
// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeFour", cmd.ExecuteNonQuery());
}
// Merge Five procedure
using (SqlCommand cmd = new SqlCommand("MergeFiveProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeFiveDataTable);
// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeFive", cmd.ExecuteNonQuery());
}
dbc.Close();
}
return recordedStatistics;
Все, что код находится в пределах того же метода, который собирает данные для DataTables. Мое ограниченное понимание async
заставило бы меня поверить, что мне нужно будет извлечь предыдущий код в свой собственный метод. Тогда я бы назвал этот метод и возвращал await
. Тем не менее, я даже не знаю достаточно об этом, чтобы начать.
Я раньше не делал асинхронного/параллельного/многопоточного кодирования. Эта ситуация только заставляет меня чувствовать, что это идеальное время для перехода. Тем не менее, я хотел бы узнать лучший способ, вместо того, чтобы отучить неправильный путь.
Это выглядит великолепно. На самом деле это приложение GUI, но я ожидаю, что он закроет GUI до тех пор, пока запросы не будут завершены. Как только они будут выполнены, я загружу представление с количеством затронутых записей из каждого из запросов. Я хочу/нуждаюсь в этой информации, поэтому я либо сижу на вызывающей странице, либо возвращаюсь к ней, как только я дам ей минутку. Я просто не видел смысла в ожидании 5 минут за запрос один за другим, когда я могу подождать те же 5 минут, чтобы все они заполнились сразу. Благодаря! – FlipperBizkut
У вас действительно есть тупик, ожидающий вызова «Task.WaitAll» в задачах, созданных «MergeOneDataTableAsync» и «MergeTwoDataTableAsync», которые оба используют 'await' без' ConfigureAwait (false) '. –
Не могли бы вы рассказать о проблеме взаимоблокировки? Возможно, есть способ избежать этого? – FlipperBizkut