【问题标题】:Dapper source code - will this dispose of my connection properly?Dapper 源代码 - 这会正确处理我的连接吗?
【发布时间】:2018-07-02 22:42:25
【问题描述】:

查看 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 块中?

【问题讨论】:

标签: dapper using


【解决方案1】:

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

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 之间的区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    • 2013-03-06
    • 1970-01-01
    • 2011-02-13
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多