Entity Framework Базовое управление соединениями - PullRequest
0 голосов
/ 26 апреля 2020

Я использую приложение 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();
            }
        }
    }
}

После этого изменения я все еще могу увидеть то же самое поведение (исключение тайм-аута подключения). Что еще я должен проверить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...