Skip to content

Commit

Permalink
FIX: Issue 120; buffered/non-buffered handling from GridReader
Browse files Browse the repository at this point in the history
  • Loading branch information
mgravell committed Oct 26, 2012
1 parent d9fedd9 commit e8ead8d
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 50 deletions.
115 changes: 66 additions & 49 deletions Dapper/SqlMapper.cs
Expand Up @@ -780,7 +780,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
#if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#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
)
{
Expand Down Expand Up @@ -808,7 +808,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
if (reader != null)
{
if (!reader.IsClosed) try { cmd.Cancel(); }
catch { /* don't spol the existing exception */ }
catch { /* don't spoil the existing exception */ }
reader.Dispose();
}
if (cmd != null) cmd.Dispose();
Expand Down Expand Up @@ -863,7 +863,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
if (reader != null)
{
if (!reader.IsClosed) try { cmd.Cancel(); }
catch { /* don't spol the existing exception */ }
catch { /* don't spoil the existing exception */ }
reader.Dispose();
}
if (wasClosed) cnn.Close();
Expand Down Expand Up @@ -2488,20 +2488,32 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
/// <summary>
/// Read the next grid of results, returned as a dynamic object
/// </summary>
public IEnumerable<dynamic> Read()
public IEnumerable<dynamic> Read(bool buffered = true)
{
return Read<DapperRow>();
return Read<DapperRow>(buffered);
}

#endif

#if CSHARP30
/// <summary>
/// Read the next grid of results
/// </summary>
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 (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);
CacheInfo cache = GetCacheInfo(typedIdentity);
var deserializer = cache.Deserializer;
Expand All @@ -2513,7 +2525,8 @@ public IEnumerable<T> Read<T>()
cache.Deserializer = deserializer;
}
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)
Expand All @@ -2538,79 +2551,83 @@ public IEnumerable<T> Read<T>()
}
}

#if CSHARP30
/// <summary>
/// Read multiple objects from a single recordset on the grid
/// </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)
{
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
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
{
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>
/// Read multiple objects from a single recordset on the grid
/// </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)
{
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
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
{
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>
/// Read multiple objects from a single record set on the grid
/// </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)
{
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
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
{
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
/// <summary>
/// Read multiple objects from a single record set on the grid
/// </summary>
/// <typeparam name="TFirst"></typeparam>
/// <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")
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> func, string splitOn = "id", bool buffered = true)
{
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

Expand Down
50 changes: 49 additions & 1 deletion Tests/Tests.cs
Expand Up @@ -728,7 +728,55 @@ public void TestMultiMapGridReader()
connection.Execute("drop table #Users drop table #Posts");

}


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()
{
var createSql = @"
Expand Down

0 comments on commit e8ead8d

Please sign in to comment.