Dapper 源代码 - 这会正确处理我的连接吗?
Dapper source code - will this dispose of my connection properly?
查看 Dappers QueryAsync 方法的源代码
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 块中?
请注意您 post 代码中的以下行:
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,....
说明QueryAsync
是IDbConnection
的扩展方法。这意味着,连接实例是在您的代码某处创建的。
如前所述,有两种方法可以管理与 Dapper 的连接:
完全管理自己:
在这里,您全权负责打开和关闭连接。这就像您在使用 ADO.NET.
时处理连接的方式一样
允许Dapper管理它:
Dapper 会自动为您打开连接(如果未打开)和关闭连接(如果它已被 Dapper 打开)。
考虑到这一点,这里唯一的选择是在您的代码中 open/close 连接或允许 Dapper 为您执行此操作。如果您自己这样做,那么 Dapper 根本不会干扰。
如果你想让Dapper为你处理open/close连接并且担心它是否会正确关闭它,那么是的,它会正确关闭它。
在您的 post 中找到以下代码:
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
....
if (wasClosed) cnn.Close();
如果 Dapper 打开连接,Dapper 会在 wasClosed
变量中维护 state/flag。您可以在代码中看到连接最后也正确关闭。此外,您可以进一步查看 Dapper 源代码以查看多个方法中的 this 是如何处理的。专门检查 SqlMapper.Async.cs
和 SqlMapper.cs
文件。
现在,这就是 open/close。 Dispose
呢?以下是 Marc Gravell 在 comment for this answer:
之一中所说的内容
well, technically open/closed is different to disposed. If you are only going to be opening/closing around the individual calls, you might as well let dapper do it. If you are opening/closing at a wider granularity (per request, for example), it would be better for your code to do it and pass an open connection to dapper.
因此,如果您真的想要 Dispose
连接而不只是 open/close,最好将其包装在代码中的 using
块中并将打开的连接传递给 Dapper。如评论中所述,this post 讨论了 Dispose
和 Close
之间的区别。
查看 Dappers QueryAsync 方法的源代码
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 块中?
请注意您 post 代码中的以下行:
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,....
说明QueryAsync
是IDbConnection
的扩展方法。这意味着,连接实例是在您的代码某处创建的。
如前所述
完全管理自己: 在这里,您全权负责打开和关闭连接。这就像您在使用 ADO.NET.
时处理连接的方式一样
允许Dapper管理它: Dapper 会自动为您打开连接(如果未打开)和关闭连接(如果它已被 Dapper 打开)。
考虑到这一点,这里唯一的选择是在您的代码中 open/close 连接或允许 Dapper 为您执行此操作。如果您自己这样做,那么 Dapper 根本不会干扰。
如果你想让Dapper为你处理open/close连接并且担心它是否会正确关闭它,那么是的,它会正确关闭它。
在您的 post 中找到以下代码:
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
....
if (wasClosed) cnn.Close();
如果 Dapper 打开连接,Dapper 会在 wasClosed
变量中维护 state/flag。您可以在代码中看到连接最后也正确关闭。此外,您可以进一步查看 Dapper 源代码以查看多个方法中的 this 是如何处理的。专门检查 SqlMapper.Async.cs
和 SqlMapper.cs
文件。
现在,这就是 open/close。 Dispose
呢?以下是 Marc Gravell 在 comment for this answer:
well, technically open/closed is different to disposed. If you are only going to be opening/closing around the individual calls, you might as well let dapper do it. If you are opening/closing at a wider granularity (per request, for example), it would be better for your code to do it and pass an open connection to dapper.
因此,如果您真的想要 Dispose
连接而不只是 open/close,最好将其包装在代码中的 using
块中并将打开的连接传递给 Dapper。如评论中所述,this post 讨论了 Dispose
和 Close
之间的区别。