Szukam właściwego sposobu obsługi wielu wywołań bazy danych, które prawdopodobnie skorzystałyby z jednoczesnego uruchamiania. Kwerendy są tylko do procedur przechowywanych, które są albo wstawia lub łączy przy użyciu danych, które są programowo zestawione w DataTables w mojej aplikacji ASP.NET MVC.Jak poprawnie wykonać asynchroniczne/równoległe wywołania bazy danych?
Oczywiście widziałem pewne informacje na temat async
i await
, i wydaje się, że to, co musiałbym zrobić, ale nie mam jasnego zrozumienia, jak go wdrożyć. Niektóre informacje mówią, że połączenia będą nadal sekwencyjne i że nadal będzie czekał na inny, aby zakończyć. To wydaje się bezcelowe.
Ostatecznie, chciałbym rozwiązania, które pozwala mi uruchomić wszystkie zapytania w czasie, który zajmuje do zakończenia najdłuższej procedury. Chciałbym, aby wszystkie zapytania zwróciły także liczbę rekordów, których dotyczy (tak jak teraz).
Oto co mam dzieje się teraz (co nie jest w żaden sposób równoległy):
// 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;
Wszystkie tego kodu jest w ramach tej samej metody, która montuje dane dla DataTables. Moje ograniczone zrozumienie async
doprowadziłoby mnie do przekonania, że będę musiał wyodrębnić poprzedni kod do własnej metody. Nazwałbym tę metodę i powrót. Jednak nie wiem wystarczająco dużo o tym, aby zacząć.
Nigdy wcześniej nie robiłem żadnego kodowania asynchronicznego/równoległego/wielowątkowego. Ta sytuacja sprawia, że czuję, że jest to idealny czas, aby wskoczyć. Powiedziałbym, że chciałbym nauczyć się najlepszego sposobu, zamiast oduczać się w niewłaściwy sposób.
To wygląda świetnie. Jest to w istocie aplikacja GUI, ale oczekuję, że zablokuje GUI, dopóki zapytania się nie zakończą. Po ich zakończeniu załaduję widok z liczbą rekordów, których dotyczy problem, z każdego z zapytań. Potrzebuję/potrzebuję tych informacji, więc albo zajmuję stronę wzywającą, albo wracam do niej, gdy doczekam jej minuty. Po prostu nie widziałem sensu w odczekaniu 5 minut na jedno zapytanie, jeden po drugim, kiedy mogę poczekać te same 5 minut, aż wszystkie zostaną ukooczone naraz. Dzięki! – FlipperBizkut
Naprawdę masz zakleszczenie czekające na wywołanie 'Task.WaitAll' na zadaniach stworzonych przez' MergeOneDataTableAsync' i 'MergeTwoDataTableAsync', które używają' await' bez 'ConfigureAwait (false)'. –
Czy możesz omówić problem z zakleszczeniem? Być może pokazać sposób na uniknięcie go również? – FlipperBizkut