提交 b87d9583 编写于 作者: M Marc Gravell

Rationalize FireOutputCallbacks, and apply to remaining methods

上级 d1e6d6f5
...@@ -52,8 +52,19 @@ public enum CommandFlags ...@@ -52,8 +52,19 @@ public enum CommandFlags
/// <summary> /// <summary>
/// Represents the key aspects of a sql operation /// Represents the key aspects of a sql operation
/// </summary> /// </summary>
public struct CommandDefinition public struct CommandDefinition
{ {
internal static CommandDefinition ForCallback(object parameters)
{
if(parameters is DynamicParameters)
{
return new CommandDefinition(parameters);
}
else
{
return default(CommandDefinition);
}
}
private readonly string commandText; private readonly string commandText;
private readonly object parameters; private readonly object parameters;
private readonly IDbTransaction transaction; private readonly IDbTransaction transaction;
...@@ -62,7 +73,13 @@ public struct CommandDefinition ...@@ -62,7 +73,13 @@ public struct CommandDefinition
private readonly CommandFlags flags; private readonly CommandFlags flags;
internal void FireOutputCallbacks()
{
if (parameters is DynamicParameters)
{
((DynamicParameters)parameters).FireOutputCallbacks();
}
}
/// <summary> /// <summary>
/// The command (sql or a stored-procedure name) to execute /// The command (sql or a stored-procedure name) to execute
/// </summary> /// </summary>
...@@ -130,6 +147,11 @@ public struct CommandDefinition ...@@ -130,6 +147,11 @@ public struct CommandDefinition
#endif #endif
} }
private CommandDefinition(object parameters) : this()
{
this.parameters = parameters;
}
#if ASYNC #if ASYNC
private readonly CancellationToken cancellationToken; private readonly CancellationToken cancellationToken;
/// <summary> /// <summary>
...@@ -1120,7 +1142,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, objec ...@@ -1120,7 +1142,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, objec
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1145,7 +1167,7 @@ public static int Execute(this IDbConnection cnn, CommandDefinition command) ...@@ -1145,7 +1167,7 @@ public static int Execute(this IDbConnection cnn, CommandDefinition command)
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1161,7 +1183,7 @@ public static int Execute(this IDbConnection cnn, CommandDefinition command) ...@@ -1161,7 +1183,7 @@ public static int Execute(this IDbConnection cnn, CommandDefinition command)
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1229,6 +1251,7 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com ...@@ -1229,6 +1251,7 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
total += cmd.ExecuteNonQuery(); total += cmd.ExecuteNonQuery();
} }
} }
command.FireOutputCallbacks();
} finally } finally
{ {
if (wasClosed) cnn.Close(); if (wasClosed) cnn.Close();
...@@ -1268,7 +1291,7 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com ...@@ -1268,7 +1291,7 @@ private static int ExecuteImpl(this IDbConnection cnn, ref CommandDefinition com
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1305,7 +1328,7 @@ public static IDataReader ExecuteReader(this IDbConnection cnn, CommandDefinitio ...@@ -1305,7 +1328,7 @@ public static IDataReader ExecuteReader(this IDbConnection cnn, CommandDefinitio
/// <summary> /// <summary>
/// Return a list of dynamic objects, reader is closed after the call /// Return a list of dynamic objects, reader is closed after the call
/// </summary> /// </summary>
public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{ {
return Query<DapperRow>(cnn, sql, param as object, transaction, buffered, commandTimeout, commandType); return Query<DapperRow>(cnn, sql, param as object, transaction, buffered, commandTimeout, commandType);
} }
...@@ -1362,7 +1385,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -1362,7 +1385,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1412,7 +1435,7 @@ public static IEnumerable<T> Query<T>(this IDbConnection cnn, CommandDefinition ...@@ -1412,7 +1435,7 @@ public static IEnumerable<T> Query<T>(this IDbConnection cnn, CommandDefinition
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1441,7 +1464,7 @@ private static GridReader QueryMultipleImpl(this IDbConnection cnn, ref CommandD ...@@ -1441,7 +1464,7 @@ private static GridReader QueryMultipleImpl(this IDbConnection cnn, ref CommandD
cmd = command.SetupCommand(cnn, info.ParamReader); cmd = command.SetupCommand(cnn, info.ParamReader);
reader = cmd.ExecuteReader(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess); reader = cmd.ExecuteReader(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess);
var result = new GridReader(cmd, reader, identity); var result = new GridReader(cmd, reader, identity, command.Parameters as DynamicParameters);
wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader
// with the CloseConnection flag, so the reader will deal with the connection; we // with the CloseConnection flag, so the reader will deal with the connection; we
// still need something in the "finally" to ensure that broken SQL still results // still need something in the "finally" to ensure that broken SQL still results
...@@ -1503,10 +1526,13 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1503,10 +1526,13 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
yield return (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture); yield return (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
} }
} }
while (reader.NextResult()) { }
// happy path; close the reader cleanly - no // happy path; close the reader cleanly - no
// need for "Cancel" etc // need for "Cancel" etc
reader.Dispose(); reader.Dispose();
reader = null; reader = null;
command.FireOutputCallbacks();
} }
finally finally
{ {
...@@ -1541,7 +1567,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1541,7 +1567,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1569,7 +1595,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1569,7 +1595,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1598,7 +1624,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1598,7 +1624,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -1626,7 +1652,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1626,7 +1652,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
/// <param name="commandType"></param> /// <param name="commandType"></param>
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>( public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
) )
{ {
return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
...@@ -1653,7 +1679,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1653,7 +1679,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
/// <param name="commandType"></param> /// <param name="commandType"></param>
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn>( public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn>(
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
) )
{ {
return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
...@@ -1681,7 +1707,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini ...@@ -1681,7 +1707,7 @@ private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefini
/// <param name="commandTimeout"></param> /// <param name="commandTimeout"></param>
/// <param name="commandType"></param> /// <param name="commandType"></param>
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
{ {
return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
...@@ -1734,6 +1760,7 @@ partial class DontMap { } ...@@ -1734,6 +1760,7 @@ partial class DontMap { }
{ {
yield return mapIt(reader); yield return mapIt(reader);
} }
command.FireOutputCallbacks();
} }
} }
finally finally
...@@ -3022,17 +3049,14 @@ private static int ExecuteCommand(IDbConnection cnn, ref CommandDefinition comma ...@@ -3022,17 +3049,14 @@ private static int ExecuteCommand(IDbConnection cnn, ref CommandDefinition comma
{ {
cmd = command.SetupCommand(cnn, paramReader); cmd = command.SetupCommand(cnn, paramReader);
if (wasClosed) cnn.Open(); if (wasClosed) cnn.Open();
return cmd.ExecuteNonQuery(); int result = cmd.ExecuteNonQuery();
command.FireOutputCallbacks();
return result;
} }
finally finally
{ {
if (wasClosed) cnn.Close(); if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose(); if (cmd != null) cmd.Dispose();
if (command.Parameters is DynamicParameters)
{
((DynamicParameters)command.Parameters).FireOutputCallbacks();
}
} }
} }
...@@ -3054,16 +3078,12 @@ private static T ExecuteScalarImpl<T>(IDbConnection cnn, ref CommandDefinition c ...@@ -3054,16 +3078,12 @@ private static T ExecuteScalarImpl<T>(IDbConnection cnn, ref CommandDefinition c
cmd = command.SetupCommand(cnn, paramReader); cmd = command.SetupCommand(cnn, paramReader);
if (wasClosed) cnn.Open(); if (wasClosed) cnn.Open();
result =cmd.ExecuteScalar(); result =cmd.ExecuteScalar();
command.FireOutputCallbacks();
} }
finally finally
{ {
if (wasClosed) cnn.Close(); if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose(); if (cmd != null) cmd.Dispose();
if (command.Parameters is DynamicParameters)
{
((DynamicParameters)command.Parameters).FireOutputCallbacks();
}
} }
return Parse<T>(result); return Parse<T>(result);
} }
...@@ -3081,17 +3101,14 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin ...@@ -3081,17 +3101,14 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin
if (wasClosed) commandBehavior |= CommandBehavior.CloseConnection; if (wasClosed) commandBehavior |= CommandBehavior.CloseConnection;
var reader = cmd.ExecuteReader(commandBehavior); var reader = cmd.ExecuteReader(commandBehavior);
wasClosed = false; // don't dispose before giving it to them! wasClosed = false; // don't dispose before giving it to them!
// note: command.FireOutputCallbacks(); would be useless here; parameters come at the **end** of the TDS stream
return reader; return reader;
} }
finally finally
{ {
if (wasClosed) cnn.Close(); if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose(); if (cmd != null) cmd.Dispose();
if (command.Parameters is DynamicParameters)
{
((DynamicParameters)command.Parameters).FireOutputCallbacks();
}
} }
} }
...@@ -3785,11 +3802,12 @@ public partial class GridReader : IDisposable ...@@ -3785,11 +3802,12 @@ public partial class GridReader : IDisposable
private IDbCommand command; private IDbCommand command;
private Identity identity; private Identity identity;
internal GridReader(IDbCommand command, IDataReader reader, Identity identity) internal GridReader(IDbCommand command, IDataReader reader, Identity identity, DynamicParameters dynamicParams)
{ {
this.command = command; this.command = command;
this.reader = reader; this.reader = reader;
this.identity = identity; this.identity = identity;
this.dynamicParams = dynamicParams;
} }
#if !CSHARP30 #if !CSHARP30
...@@ -3996,6 +4014,8 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese ...@@ -3996,6 +4014,8 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese
} }
private int gridIndex, readCount; private int gridIndex, readCount;
private bool consumed; private bool consumed;
private DynamicParameters dynamicParams;
/// <summary> /// <summary>
/// Has the underlying reader been consumed? /// Has the underlying reader been consumed?
/// </summary> /// </summary>
...@@ -4020,7 +4040,7 @@ private void NextResult() ...@@ -4020,7 +4040,7 @@ private void NextResult()
// need for "Cancel" etc // need for "Cancel" etc
reader.Dispose(); reader.Dispose();
reader = null; reader = null;
if (dynamicParams != null) dynamicParams.FireOutputCallbacks();
Dispose(); Dispose();
} }
} }
......
...@@ -95,13 +95,15 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, ...@@ -95,13 +95,15 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
{ {
buffer.Add((T)func(reader)); buffer.Add((T)func(reader));
} }
while (await reader.NextResultAsync().ConfigureAwait(false)) { }
command.FireOutputCallbacks();
return buffer; return buffer;
} }
else else
{ {
// can't use ReadAsync / cancellation; but this will have to do // 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 wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
var deferred = ExecuteReaderSync<T>(reader, func); var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it reader = null; // to prevent it being disposed before the caller gets to see it
return deferred; return deferred;
} }
...@@ -211,7 +213,6 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD ...@@ -211,7 +213,6 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
using (pending.Dequeue().Command) { } // dispose commands using (pending.Dequeue().Command) { } // dispose commands
} }
} }
return total;
} }
else else
{ {
...@@ -236,6 +237,8 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD ...@@ -236,6 +237,8 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
} }
} }
} }
command.FireOutputCallbacks();
} }
finally finally
{ {
...@@ -253,7 +256,9 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini ...@@ -253,7 +256,9 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
try try
{ {
if (wasClosed) await ((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false); if (wasClosed) await ((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
return await cmd.ExecuteNonQueryAsync(command.CancellationToken).ConfigureAwait(false); var result = await cmd.ExecuteNonQueryAsync(command.CancellationToken).ConfigureAwait(false);
command.FireOutputCallbacks();
return result;
} }
finally finally
{ {
...@@ -446,7 +451,7 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini ...@@ -446,7 +451,7 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
using (var reader = await cmd.ExecuteReaderAsync(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false)) using (var reader = await cmd.ExecuteReaderAsync(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false))
{ {
if (!command.Buffered) wasClosed = false; // handing back open reader; rely on command-behavior if (!command.Buffered) wasClosed = false; // handing back open reader; rely on command-behavior
var results = MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, default(CommandDefinition), map, splitOn, reader, identity); var results = MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, CommandDefinition.ForCallback(command.Parameters), map, splitOn, reader, identity);
return command.Buffered ? results.ToList() : results; return command.Buffered ? results.ToList() : results;
} }
} finally } finally
...@@ -455,12 +460,15 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini ...@@ -455,12 +460,15 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
} }
} }
private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDataReader,object> func) private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDataReader,object> func, object parameters)
{ {
while (reader.Read()) while (reader.Read())
{ {
yield return (T)func(reader); yield return (T)func(reader);
} }
while (reader.NextResult()) { }
if (parameters is DynamicParameters)
((DynamicParameters)parameters).FireOutputCallbacks();
} }
/// <summary> /// <summary>
...@@ -481,7 +489,7 @@ private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDat ...@@ -481,7 +489,7 @@ private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDat
partial class GridReader partial class GridReader
{ {
CancellationToken cancel; CancellationToken cancel;
internal GridReader(IDbCommand command, IDataReader reader, Identity identity, CancellationToken cancel) : this(command, reader, identity) internal GridReader(IDbCommand command, IDataReader reader, Identity identity, DynamicParameters dynamicParams, CancellationToken cancel) : this(command, reader, identity, dynamicParams)
{ {
this.cancel = cancel; this.cancel = cancel;
} }
...@@ -524,7 +532,7 @@ private async Task NextResultAsync() ...@@ -524,7 +532,7 @@ private async Task NextResultAsync()
// need for "Cancel" etc // need for "Cancel" etc
reader.Dispose(); reader.Dispose();
reader = null; reader = null;
if (dynamicParams != null) dynamicParams.FireOutputCallbacks();
Dispose(); Dispose();
} }
} }
...@@ -600,7 +608,7 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn, ...@@ -600,7 +608,7 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader); cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader);
reader = await cmd.ExecuteReaderAsync(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false); reader = await cmd.ExecuteReaderAsync(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false);
var result = new GridReader(cmd, reader, identity, command.CancellationToken); var result = new GridReader(cmd, reader, identity, command.Parameters as DynamicParameters, command.CancellationToken);
wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader
// with the CloseConnection flag, so the reader will deal with the connection; we // with the CloseConnection flag, so the reader will deal with the connection; we
// still need something in the "finally" to ensure that broken SQL still results // still need something in the "finally" to ensure that broken SQL still results
...@@ -758,6 +766,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman ...@@ -758,6 +766,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman
cmd = (DbCommand)command.SetupCommand(cnn, paramReader); cmd = (DbCommand)command.SetupCommand(cnn, paramReader);
if (wasClosed) await ((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false); if (wasClosed) await ((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
result = await cmd.ExecuteScalarAsync(command.CancellationToken).ConfigureAwait(false); result = await cmd.ExecuteScalarAsync(command.CancellationToken).ConfigureAwait(false);
command.FireOutputCallbacks();
} }
finally finally
{ {
......
...@@ -355,5 +355,199 @@ public void Issue22_ExecuteScalar() ...@@ -355,5 +355,199 @@ public void Issue22_ExecuteScalar()
k.IsNull(); k.IsNull();
} }
} }
public void TestSupportForDynamicParametersOutputExpressions()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
connection.ExecuteAsync(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId", p).Wait();
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
}
}
public void TestSupportForDynamicParametersOutputExpressions_Scalar()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = (int)connection.ExecuteScalarAsync(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p).Result;
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_Query_Default()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = connection.QueryAsync<int>(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p).Result.Single();
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_Query_Buffered()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = connection.QueryAsync<int>(new CommandDefinition(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p, flags: CommandFlags.Buffered)).Result.Single();
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_Query_NonBuffered()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = connection.QueryAsync<int>(new CommandDefinition(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p, flags: CommandFlags.None)).Result.Single();
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_QueryMultiple()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
int x, y;
using(var multi = connection.QueryMultipleAsync(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
select 42
select 17
SET @AddressPersonId = @PersonId", p).Result)
{
x = multi.ReadAsync<int>().Result.Single();
y = multi.ReadAsync<int>().Result.Single();
}
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
x.IsEqualTo(42);
y.IsEqualTo(17);
}
}
class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public string Occupation { get; private set; }
public int NumberOfLegs = 2;
public Address Address { get; set; }
}
class Address
{
public int AddressId { get; set; }
public string Name { get; set; }
public int PersonId { get; set; }
}
} }
} }
\ No newline at end of file
...@@ -1201,7 +1201,130 @@ public void TestSupportForDynamicParametersOutputExpressions() ...@@ -1201,7 +1201,130 @@ public void TestSupportForDynamicParametersOutputExpressions()
bob.Address.Name.IsEqualTo("bobs burgers"); bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2); bob.Address.PersonId.IsEqualTo(2);
} }
public void TestSupportForDynamicParametersOutputExpressions_Scalar()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = (int)connection.ExecuteScalar(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p);
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_Query_Buffered()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = connection.Query<int>(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p, buffered: true).Single();
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_Query_NonBuffered()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
var result = connection.Query<int>(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
SET @AddressPersonId = @PersonId
select 42", p, buffered: false).Single();
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
result.IsEqualTo(42);
}
}
public void TestSupportForDynamicParametersOutputExpressions_QueryMultiple()
{
using (var connection = Program.GetOpenConnection())
{
var bob = new Person { Name = "bob", PersonId = 1, Address = new Address { PersonId = 2 } };
var p = new DynamicParameters(bob);
p.Output(bob, b => b.PersonId);
p.Output(bob, b => b.Occupation);
p.Output(bob, b => b.NumberOfLegs);
p.Output(bob, b => b.Address.Name);
p.Output(bob, b => b.Address.PersonId);
int x, y;
using (var multi = connection.QueryMultiple(@"
SET @Occupation = 'grillmaster'
SET @PersonId = @PersonId + 1
SET @NumberOfLegs = @NumberOfLegs - 1
SET @AddressName = 'bobs burgers'
select 42
select 17
SET @AddressPersonId = @PersonId", p))
{
x = multi.Read<int>().Single();
y = multi.Read<int>().Single();
}
bob.Occupation.IsEqualTo("grillmaster");
bob.PersonId.IsEqualTo(2);
bob.NumberOfLegs.IsEqualTo(1);
bob.Address.Name.IsEqualTo("bobs burgers");
bob.Address.PersonId.IsEqualTo(2);
x.IsEqualTo(42);
y.IsEqualTo(17);
}
}
public void TestSupportForExpandoObjectParameters() public void TestSupportForExpandoObjectParameters()
{ {
dynamic p = new ExpandoObject(); dynamic p = new ExpandoObject();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册