Dapper源代码-这样可以正确处理我的连接吗?

时间:2018-06-27 11:24:43

标签: dapper using

查看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 :(得分:0)

请注意您发布的代码中的以下行:

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

这表明QueryAsyncIDbConnection的扩展方法。也就是说,连接实例是在您的代码中的某个地方创建的

here所述,有两种方法可以管理与Dapper的连接:

  • 完全管理自己: 在这里,您完全负责打开和关闭连接。就像在使用ADO.NET时如何对待连接一样。

  • 允许Dapper对其进行管理: Dapper会自动为您打开连接(如果未打开)并关闭(如果Dapper打开了)。

考虑到这一点,剩下的唯一选择就是在代码中打开/关闭连接,或者允许Dapper为您执行此操作。如果您自己这样做,那么Dapper根本不会干涉。

如果要允许Dapper为您处理打开/关闭连接,并担心它是否会正确关闭,则可以,它会正确关闭。

在您的帖子中找到以下代码:

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

如果Dapper打开了连接,则Dapper维护wasClosed变量中的状态/标志。您可以在代码中看到该连接最后也已正确关闭。此外,您可以进一步检查Dapper源代码,以查看如何在多种方法中处理此问题。专门检查SqlMapper.Async.csSqlMapper.cs文件。

现在,这一切都与打开/关闭有关。 Dispose呢?以下是马克·格雷夫(Marc Gravell)在comment的其中一个答案中所说的:https://stackoverflow.com/a/12629170/5779732

  嗯,技术上来说,打开/关闭与处置不同。如果您只打算在各个呼叫之间打开/关闭,最好还是让dapper来做。 如果您以更大的粒度(例如,按请求)打开/关闭,则最好代码执行此操作并将打开的连接传递给dapper。

因此,如果您真的想Dispose连接而不只是打开/关闭,则最好将其包装在代码的using块中,然后将打开的连接传递给Dapper。如评论中所述,this帖子讨论了DisposeClose之间的区别。