Commit b87d9583 authored by Marc Gravell's avatar Marc Gravell

Rationalize FireOutputCallbacks, and apply to remaining methods

parent d1e6d6f5
This diff is collapsed.
...@@ -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% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment