diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 3f50a6dda..de32b0f77 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -780,7 +780,7 @@ public static IEnumerable 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 ) { @@ -808,7 +808,7 @@ public static IEnumerable 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(); @@ -863,7 +863,7 @@ private static IEnumerable QueryInternal(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(); @@ -2488,20 +2488,32 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity) /// /// Read the next grid of results, returned as a dynamic object /// - public IEnumerable Read() + public IEnumerable Read(bool buffered = true) { - return Read(); + return Read(buffered); } - #endif +#if CSHARP30 /// /// Read the next grid of results /// public IEnumerable Read() + { + return Read(true); + } +#endif + /// + /// Read the next grid of results + /// +#if CSHARP30 + public IEnumerable Read(bool buffered) +#else + public IEnumerable Read(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; @@ -2513,7 +2525,8 @@ public IEnumerable Read() cache.Deserializer = deserializer; } consumed = true; - return ReadDeferred(gridIndex, deserializer.Func, typedIdentity); + var result = ReadDeferred(gridIndex, deserializer.Func, typedIdentity); + return buffered ? result.ToList() : result; } private IEnumerable MultiReadInternal(object func, string splitOn) @@ -2538,79 +2551,83 @@ public IEnumerable Read() } } +#if CSHARP30 /// /// Read multiple objects from a single recordset on the grid /// - /// - /// - /// - /// - /// - /// -#if CSHARP30 public IEnumerable Read(Func func, string splitOn) + { + return Read(func, splitOn, true); + } +#endif + /// + /// Read multiple objects from a single recordset on the grid + /// +#if CSHARP30 + public IEnumerable Read(Func func, string splitOn, bool buffered) #else - public IEnumerable Read(Func func, string splitOn = "id") + public IEnumerable Read(Func func, string splitOn = "id", bool buffered = true) #endif { - return MultiReadInternal(func, splitOn); + var result = MultiReadInternal(func, splitOn); + return buffered ? result.ToList() : result; } +#if CSHARP30 /// /// Read multiple objects from a single recordset on the grid /// - /// - /// - /// - /// - /// - /// - /// -#if CSHARP30 public IEnumerable Read(Func func, string splitOn) + { + return Read(func, splitOn, true); + } +#endif + /// + /// Read multiple objects from a single recordset on the grid + /// +#if CSHARP30 + public IEnumerable Read(Func func, string splitOn, bool buffered) #else - public IEnumerable Read(Func func, string splitOn = "id") + public IEnumerable Read(Func func, string splitOn = "id", bool buffered = true) #endif { - return MultiReadInternal(func, splitOn); + var result = MultiReadInternal(func, splitOn); + return buffered ? result.ToList() : result; } +#if CSHARP30 /// /// Read multiple objects from a single record set on the grid /// - /// - /// - /// - /// - /// - /// - /// - /// -#if CSHARP30 public IEnumerable Read(Func func, string splitOn) + { + return Read(func, splitOn, true); + } +#endif + + /// + /// Read multiple objects from a single record set on the grid + /// +#if CSHARP30 + public IEnumerable Read(Func func, string splitOn, bool buffered) #else - public IEnumerable Read(Func func, string splitOn = "id") + public IEnumerable Read(Func func, string splitOn = "id", bool buffered = true) #endif { - return MultiReadInternal(func, splitOn); + var result = MultiReadInternal(func, splitOn); + return buffered ? result.ToList() : result; } + + #if !CSHARP30 /// /// Read multiple objects from a single record set on the grid /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public IEnumerable Read(Func func, string splitOn = "id") + public IEnumerable Read(Func func, string splitOn = "id", bool buffered = true) { - return MultiReadInternal(func, splitOn); + var result = MultiReadInternal(func, splitOn); + return buffered ? result.ToList() : result; } #endif diff --git a/Tests/Tests.cs b/Tests/Tests.cs index d6e86a9ba..dc38c55a8 100644 --- a/Tests/Tests.cs +++ b/Tests/Tests.cs @@ -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(); + var b = grid.Read(); + var c = grid.Read(); + var d = grid.Read(); + + 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(false); + try + { + var b = grid.Read(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(false).Single(); + var b = grid.Read(false).Single(); + var c = grid.Read(false).Single(); + var d = grid.Read(false).Single(); + + a.Equals(1); + b.Equals(2); + c.Equals(3); + d.Equals(4); + } + } public void TestMultiMapDynamic() { var createSql = @"