Commit e8ead8d8 authored by Marc Gravell's avatar Marc Gravell

FIX: Issue 120; buffered/non-buffered handling from GridReader

parent d9fedd9b
...@@ -780,7 +780,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -780,7 +780,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, 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, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -808,7 +808,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -808,7 +808,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
if (reader != null) if (reader != null)
{ {
if (!reader.IsClosed) try { cmd.Cancel(); } if (!reader.IsClosed) try { cmd.Cancel(); }
catch { /* don't spol the existing exception */ } catch { /* don't spoil the existing exception */ }
reader.Dispose(); reader.Dispose();
} }
if (cmd != null) cmd.Dispose(); if (cmd != null) cmd.Dispose();
...@@ -863,7 +863,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -863,7 +863,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
if (reader != null) if (reader != null)
{ {
if (!reader.IsClosed) try { cmd.Cancel(); } if (!reader.IsClosed) try { cmd.Cancel(); }
catch { /* don't spol the existing exception */ } catch { /* don't spoil the existing exception */ }
reader.Dispose(); reader.Dispose();
} }
if (wasClosed) cnn.Close(); if (wasClosed) cnn.Close();
...@@ -2488,20 +2488,32 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity) ...@@ -2488,20 +2488,32 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
/// <summary> /// <summary>
/// Read the next grid of results, returned as a dynamic object /// Read the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
public IEnumerable<dynamic> Read() public IEnumerable<dynamic> Read(bool buffered = true)
{ {
return Read<DapperRow>(); return Read<DapperRow>(buffered);
} }
#endif #endif
#if CSHARP30
/// <summary> /// <summary>
/// Read the next grid of results /// Read the next grid of results
/// </summary> /// </summary>
public IEnumerable<T> Read<T>() public IEnumerable<T> Read<T>()
{
return Read<T>(true);
}
#endif
/// <summary>
/// Read the next grid of results
/// </summary>
#if CSHARP30
public IEnumerable<T> Read<T>(bool buffered)
#else
public IEnumerable<T> Read<T>(bool buffered = true)
#endif
{ {
if (reader == null) throw new ObjectDisposedException(GetType().FullName, "The reader has been disposed; this can happen after all data has been consumed"); if (reader == null) throw new ObjectDisposedException(GetType().FullName, "The reader has been disposed; this can happen after all data has been consumed");
if (consumed) throw new InvalidOperationException("Each grid can only be iterated once"); if (consumed) throw new InvalidOperationException("Query results must be consumed in the correct order, and each result can only be consumed once");
var typedIdentity = identity.ForGrid(typeof(T), gridIndex); var typedIdentity = identity.ForGrid(typeof(T), gridIndex);
CacheInfo cache = GetCacheInfo(typedIdentity); CacheInfo cache = GetCacheInfo(typedIdentity);
var deserializer = cache.Deserializer; var deserializer = cache.Deserializer;
...@@ -2513,7 +2525,8 @@ public IEnumerable<T> Read<T>() ...@@ -2513,7 +2525,8 @@ public IEnumerable<T> Read<T>()
cache.Deserializer = deserializer; cache.Deserializer = deserializer;
} }
consumed = true; consumed = true;
return ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity); var result = ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity);
return buffered ? result.ToList() : result;
} }
private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(object func, string splitOn) private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(object func, string splitOn)
...@@ -2538,79 +2551,83 @@ public IEnumerable<T> Read<T>() ...@@ -2538,79 +2551,83 @@ public IEnumerable<T> Read<T>()
} }
} }
#if CSHARP30
/// <summary> /// <summary>
/// Read multiple objects from a single recordset on the grid /// Read multiple objects from a single recordset on the grid
/// </summary> /// </summary>
/// <typeparam name="TFirst"></typeparam>
/// <typeparam name="TSecond"></typeparam>
/// <typeparam name="TReturn"></typeparam>
/// <param name="func"></param>
/// <param name="splitOn"></param>
/// <returns></returns>
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn) public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn)
{
return Read<TFirst, TSecond, TReturn>(func, splitOn, true);
}
#endif
/// <summary>
/// Read multiple objects from a single recordset on the grid
/// </summary>
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn, bool buffered)
#else #else
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id") public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id", bool buffered = true)
#endif #endif
{ {
return MultiReadInternal<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(func, splitOn); var result = MultiReadInternal<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(func, splitOn);
return buffered ? result.ToList() : result;
} }
#if CSHARP30
/// <summary> /// <summary>
/// Read multiple objects from a single recordset on the grid /// Read multiple objects from a single recordset on the grid
/// </summary> /// </summary>
/// <typeparam name="TFirst"></typeparam>
/// <typeparam name="TSecond"></typeparam>
/// <typeparam name="TThird"></typeparam>
/// <typeparam name="TReturn"></typeparam>
/// <param name="func"></param>
/// <param name="splitOn"></param>
/// <returns></returns>
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn) public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn)
{
return Read<TFirst, TSecond, TThird, TReturn>(func, splitOn, true);
}
#endif
/// <summary>
/// Read multiple objects from a single recordset on the grid
/// </summary>
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn, bool buffered)
#else #else
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id") public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id", bool buffered = true)
#endif #endif
{ {
return MultiReadInternal<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(func, splitOn); var result = MultiReadInternal<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(func, splitOn);
return buffered ? result.ToList() : result;
} }
#if CSHARP30
/// <summary> /// <summary>
/// Read multiple objects from a single record set on the grid /// Read multiple objects from a single record set on the grid
/// </summary> /// </summary>
/// <typeparam name="TFirst"></typeparam>
/// <typeparam name="TSecond"></typeparam>
/// <typeparam name="TThird"></typeparam>
/// <typeparam name="TFourth"></typeparam>
/// <typeparam name="TReturn"></typeparam>
/// <param name="func"></param>
/// <param name="splitOn"></param>
/// <returns></returns>
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn) public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
{
return Read<TFirst, TSecond, TThird, TFourth, TReturn>(func, splitOn, true);
}
#endif
/// <summary>
/// Read multiple objects from a single record set on the grid
/// </summary>
#if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn, bool buffered)
#else #else
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id") public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id", bool buffered = true)
#endif #endif
{ {
return MultiReadInternal<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(func, splitOn); var result = MultiReadInternal<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(func, splitOn);
return buffered ? result.ToList() : result;
} }
#if !CSHARP30 #if !CSHARP30
/// <summary> /// <summary>
/// Read multiple objects from a single record set on the grid /// Read multiple objects from a single record set on the grid
/// </summary> /// </summary>
/// <typeparam name="TFirst"></typeparam> public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> func, string splitOn = "id", bool buffered = true)
/// <typeparam name="TSecond"></typeparam>
/// <typeparam name="TThird"></typeparam>
/// <typeparam name="TFourth"></typeparam>
/// <typeparam name="TFifth"></typeparam>
/// <typeparam name="TReturn"></typeparam>
/// <param name="func"></param>
/// <param name="splitOn"></param>
/// <returns></returns>
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> func, string splitOn = "id")
{ {
return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(func, splitOn); var result = MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(func, splitOn);
return buffered ? result.ToList() : result;
} }
#endif #endif
......
...@@ -729,6 +729,54 @@ public void TestMultiMapGridReader() ...@@ -729,6 +729,54 @@ public void TestMultiMapGridReader()
} }
public void TestQueryMultipleBuffered()
{
using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
{
var a = grid.Read<int>();
var b = grid.Read<int>();
var c = grid.Read<int>();
var d = grid.Read<int>();
a.Single().Equals(1);
b.Single().Equals(2);
c.Single().Equals(3);
d.Single().Equals(4);
}
}
public void TestQueryMultipleNonBufferedIncorrectOrder()
{
using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
{
var a = grid.Read<int>(false);
try
{
var b = grid.Read<int>(false);
throw new InvalidOperationException(); // should have thrown
}
catch (InvalidOperationException)
{
// that's expected
}
}
}
public void TestQueryMultipleNonBufferedCcorrectOrder()
{
using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
{
var a = grid.Read<int>(false).Single();
var b = grid.Read<int>(false).Single();
var c = grid.Read<int>(false).Single();
var d = grid.Read<int>(false).Single();
a.Equals(1);
b.Equals(2);
c.Equals(3);
d.Equals(4);
}
}
public void TestMultiMapDynamic() public void TestMultiMapDynamic()
{ {
var createSql = @" var createSql = @"
......
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