Красивый исходный код - будет ли это правильно удалять моё соединение? - PullRequest
0 голосов
/ 27 июня 2018

Просмотр исходного кода для метода Dappers QueryAsync

SqlMapper.Async.cs

 private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
    {

        using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))
        {
            DbDataReader reader = null;
            try
            {
                if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);

                var func = tuple.Func;

                if (command.Buffered)
                {
                    var buffer = new List<T>();
                    var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
                    while (await reader.ReadAsync(cancel).ConfigureAwait(false))
                    {
                        object val = func(reader);
                        if (val == null || val is T)
                        {
                            buffer.Add((T)val);
                        }
                        else
                        {
                            buffer.Add((T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture));
                        }
                    }
                    while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent result sets */ }
                    command.OnCompleted();
                    return buffer;
                }
                else
                {
                    // can't use ReadAsync / cancellation; but this will have to do
                    wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
                    var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
                    reader = null; // to prevent it being disposed before the caller gets to see it
                    return deferred;
                }
            }
            finally
            {
                using (reader) { /* dispose if non-null */ }
                if (wasClosed) cnn.Close();
            }
        }
    }

Обратите внимание на эту строку (413):

using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))

У меня такой вопрос, будет ли мое соединение корректно удалено, и мне не нужно будет оборачивать свой код, обращаясь к этому, в блоке using?

1 Ответ

0 голосов
/ 02 июля 2018

Обратите внимание на следующую строку в коде, который вы публикуете:

private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,....

Показывает, что QueryAsync - это метод расширения IDbConnection. Это означает, что экземпляр соединения создан в вашем коде где-то.

Как уже упоминалось здесь , существует два способа управления соединением с Dapper:

  • Полностью управляй собой: Здесь вы несете полную ответственность за открытие и закрытие соединения. Это так же, как вы относитесь к соединению при работе с ADO.NET.

  • Разрешить Dapper управлять им: Dapper автоматически открывает соединение (если оно не было открыто) и закрывает его (если оно было открыто Dapper) для вас.

Учитывая это, остается только один вариант: открыть / закрыть соединение в вашем коде или позволить Dapper сделать это за вас. Если вы делаете это самостоятельно, Даппер не мешает вообще.

Если вы хотите разрешить Dapper обрабатывать соединение открытия / закрытия для вас и беспокоитесь о том, правильно ли он закроет его, тогда да, он закроет его правильно.

Найдите следующий код в вашем сообщении:

if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
....
if (wasClosed) cnn.Close();

Dapper поддерживает состояние / флаг в переменной wasClosed, если соединение было открыто Dapper. Вы можете видеть в своем коде, что соединение также правильно закрыто в конце. Кроме того, вы можете дополнительно проверить исходный код Dapper, чтобы увидеть, как это обрабатывается несколькими методами. Специально проверьте файлы SqlMapper.Async.cs и SqlMapper.cs.

Теперь все дело в открытии / закрытии. А как насчет Dispose? Вот что говорит Марк Гравелл в одном из комментариев для этого ответа: https://stackoverflow.com/a/12629170/5779732

ну, технически открытый / закрытый отличается от утилизируемого. Если вы собираетесь открывать / закрывать только отдельные вызовы, вы можете позволить dapper сделать это. Если вы открываете / закрываете с более высокой степенью детализации (например, для каждого запроса), для вашего кода было бы лучше сделать это и передать открытое соединение dapper.

Итак, если вы действительно хотите Dispose установить соединение вместо того, чтобы просто открывать / закрывать, лучше оберните его в блок using в своем коде и передайте открытое соединение в Dapper. Как упомянуто в комментарии, эта запись обсуждает разницу между Dispose и Close.

...