Я использую приложение C# (v2.2), которое обращается к моей базе данных (MySQL) с помощью Entity Framework.
Это мой код:
public static async Task<int> IncerementByAsync(string id, int incrBy, string counterType)
{
using (var context = new CacheDbContext())
{
int result = 0;
using (var command = context.Database.GetDbConnection().CreateCommand())
{
if (command.Connection.State != ConnectionState.Open)
{
Console.WriteLine($"Connection staus is {command.Connection.State.ToString()}. Opening");
context.Database.OpenConnection();
}
command.CommandType = CommandType.StoredProcedure;
command.CommandText = $"Counter_increment2";
command.Parameters.Add(new MySqlParameter("_Id", id));
command.Parameters.Add(new MySqlParameter("_CounterType", counterType));
command.Parameters.Add(new MySqlParameter("_IncrBy", incrBy));
command.Parameters[command.Parameters.Add(new MySqlParameter("_NewValue", result))].Direction = ParameterDirection.Output;
await command.ExecuteNonQueryAsync().ConfigureAwait(false);
return (int)command.Parameters[3].Value; // Read output parameter
}
}
}
Я запускаю хранимую процедуру Counter_increment2
и считываю параметр OUT
из ответа.
Когда я тестировал его в среде разработки - он работает нормально. При тестировании в производственной среде, когда было сделано много звонков, я начал время от времени получать ошибки:
MySql .Data.MySqlClient.MySqlException (0x80004005): Connect Тайм-аут истек.
System.OperationCanceledException: операция была отменена.
в System.Threading.SemaphoreSlim.Wait (Int32 миллисекундыTimeout, CancellationToken cancellationToken)
в MySqlConnector.Core.ConnectionPool.GetSessionAsyn c (соединение MySqlConnection, переход в класс Iobeach, переход в класс IOb) \ projects \ mysqlconnector \ src \ MySqlConnector \ Core \ ConnectionPool.cs: строка 46
в MySql .Data.MySqlClient.MySqlConnection.CreateSessionAsyn c (Nullable 1 ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlConnection.cs:line 507<br>
at MySql.Data.MySqlClient.MySqlConnection.CreateSessionAsync(Nullable
1 ioBehavior, отмена отмены * 1050 в режиме отмены) : \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql .Data.MySqlClient \ MySqlConnection.cs: строка 523
в MySql .Data.MySqlClient.MySqlConnection.OpenAsyn c (операция Nullable * 10, 10) Func`3 verifySucceeded) в Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.OpenConnection (DatabaseFacade databaseFacade) в ***. IncrementByAsyn c (идентификатор строки, Int32 incrBy, тип строки String counterType) в /****/CounterOperations.: 1022 *
Строка подключения к моей БД ограничивает количество одновременных соединений для определенного числа. Я предполагаю, что в какой-то момент все дополнительные соединения были использованы, и я получил исключение времени соединения.
Поскольку я использую пул соединений EF, я ожидал повторного использования соединений из пула. Удивительно, но при каждом вызове функции открывалось новое соединение. Это распечатка, которую я получаю при каждом звонке:
Состояние соединения закрыто. Открытие
Это означает, что соединение открывается при каждом вводе этого кода.
Должно быть, здесь какой-то неправильный код, иначе у меня не было таких проблем с подключением. Но что я делаю не так? Как управлять подключением к моей базе данных?
Обновление 1
Согласно комментарию @Ivan, я изменил код так:
public static async Task<int> IncerementByAsync(string id, int incrBy, string counterType)
{
using (var context = new CacheDbContext())
{
int result = 0;
using (var command = context.Database.GetDbConnection().CreateCommand())
{
bool wasOpen = command.Connection.State == ConnectionState.Open;
if (!wasOpen)
{
Console.WriteLine($"Connection status is {command.Connection.State.ToString()}. Opening");
context.Database.OpenConnection();
}
try
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = $"Counter_increment2";
command.Parameters.Add(new MySqlParameter("_Id", id));
command.Parameters.Add(new MySqlParameter("_CounterType", counterType));
command.Parameters.Add(new MySqlParameter("_IncrBy", incrBy));
command.Parameters[command.Parameters.Add(new MySqlParameter("_NewValue", result))].Direction = ParameterDirection.Output;
await command.ExecuteNonQueryAsync().ConfigureAwait(false);
return (int)command.Parameters[3].Value; // Read output parameter
}
finally
{
if (!wasOpen)
command.Connection.Close();
}
}
}
}
После этого изменения я все еще могу увидеть то же самое поведение (исключение тайм-аута подключения). Что еще я должен проверить?