Dapper código fuente: ¿esto eliminará mi conexión correctamente?

dapper using

Pregunta

Mirando el código fuente para el método 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();
            }
        }
    }

Tenga en cuenta esta línea (413):

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

Mi pregunta es, ¿mi conexión se eliminará correctamente sin tener que envolver mi código llamando a esto en un bloque de uso?

Respuesta aceptada

Tenga en cuenta la siguiente línea en el código que publica:

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

Eso muestra que QueryAsync es un método de extensión de IDbConnection . Eso significa que la instancia de conexión se crea en su código en alguna parte.

Como se mencionó aquí , hay dos formas de administrar la conexión con Dapper:

  • Administrate por completo: aquí, eres completamente responsable de abrir y cerrar la conexión. Así es como trata la conexión mientras trabaja con ADO.NET.

  • Permita que Dapper lo administre: Dapper automáticamente abre la conexión (si no se abrió) y la cierra (si fue creada por Dapper) por usted.

Teniendo en cuenta esto, la única opción que queda aquí es abrir / cerrar la conexión en su código o permitir que Dapper lo haga por usted. Si haces esto tú mismo, Dapper no interfiere en absoluto.

Si desea permitir que Dapper maneje la conexión de apertura / cierre para usted y le preocupa que se cierre correctamente, entonces sí, lo cierra correctamente.

Encuentra el siguiente código en tu publicación:

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

Dapper mantiene el estado / indicador en la variable wasClosed si la conexión fue abierta por Dapper. Puede ver en su código que la conexión también se cierra correctamente al final. Además, puede verificar el código fuente de Dapper para ver cómo se maneja esto en múltiples métodos. Revise especialmente los archivos SqlMapper.Async.cs y SqlMapper.cs .

Ahora, todo esto se trata de abrir / cerrar. ¿Qué hay de Dispose ? A continuación se muestra lo que Marc Gravell dice en uno de los comentarios para esta respuesta: https://stackoverflow.com/a/12629170/5779732

bien, técnicamente abierto / cerrado es diferente a lo dispuesto. Si solo vas a estar abriendo / cerrando alrededor de las llamadas individuales, también puedes dejar que apresuradamente lo hagas. Si está abriendo / cerrando en una granularidad más amplia (por solicitud, por ejemplo), sería mejor para su código hacerlo y pasar una conexión abierta a apuesto.

Entonces, si realmente quiere Dispose la conexión en lugar de simplemente abrir / cerrar, mejor la envuelve using bloque en su código y pasa la conexión abierta a Dapper. Como se menciona en el comentario, esta publicación analiza la diferencia entre Dispose y Close .



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué