查看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块中?
答案 0 :(得分:0)
请注意您发布的代码中的以下行:
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,....
这表明QueryAsync
是IDbConnection
的扩展方法。也就是说,连接实例是在您的代码中的某个地方创建的。
如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.cs
和SqlMapper.cs
文件。
现在,这一切都与打开/关闭有关。 Dispose
呢?以下是马克·格雷夫(Marc Gravell)在comment的其中一个答案中所说的:https://stackoverflow.com/a/12629170/5779732
嗯,技术上来说,打开/关闭与处置不同。如果您只打算在各个呼叫之间打开/关闭,最好还是让dapper来做。 如果您以更大的粒度(例如,按请求)打开/关闭,则最好代码执行此操作并将打开的连接传递给dapper。
因此,如果您真的想Dispose
连接而不只是打开/关闭,则最好将其包装在代码的using
块中,然后将打开的连接传递给Dapper。如评论中所述,this帖子讨论了Dispose
和Close
之间的区别。