using System; using System.Collections.Generic; using System.Data; using System.Linq; using Xunit; namespace Dapper.Tests { public class QueryMultipleTests : TestBase { [Fact] 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); } } [Fact] 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 } } } [Fact] public void TestQueryMultipleNonBufferedCorrectOrder() { 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); } } [Fact] public void TestMultiReaderBasic() { const string sql = "select 1 as Id union all select 2 as Id select 'abc' as name select 1 as Id union all select 2 as Id"; int i, j; string s; using (var multi = connection.QueryMultiple(sql)) { i = multi.Read().First(); s = multi.Read().Single(); j = multi.Read().Sum(); } Assert.Equal(1, i); Assert.Equal("abc", s); Assert.Equal(3, j); } [Fact] public void TestReadDynamicWithGridReader() { const string createSql = @" create table #Users (Id int, Name varchar(20)) create table #Posts (Id int, OwnerId int, Content varchar(20)) insert #Users values(99, 'Sam') insert #Users values(2, 'I am') insert #Posts values(1, 99, 'Sams Post1') insert #Posts values(2, 99, 'Sams Post2') insert #Posts values(3, null, 'no ones post')"; try { connection.Execute(createSql); const string sql = @"SELECT * FROM #Users ORDER BY Id SELECT * FROM #Posts ORDER BY Id DESC"; var grid = connection.QueryMultiple(sql); var users = grid.Read().ToList(); var posts = grid.Read().ToList(); Assert.Equal(2, users.Count); Assert.Equal(3, posts.Count); Assert.Equal(2, (int)users[0].Id); Assert.Equal(3, (int)posts[0].Id); } finally { connection.Execute("drop table #Users drop table #Posts"); } } [Fact] public void Issue268_ReturnQueryMultiple() { connection.Execute(@"create proc #TestProc268 (@a int, @b int, @c int)as begin select @a; select @b return @c; end"); var p = new DynamicParameters(new { a = 1, b = 2, c = 3 }); p.Add("RetVal", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue); using (var reader = connection.QueryMultiple("#TestProc268", p, commandType: CommandType.StoredProcedure)) { reader.Read(); } var retVal = p.Get("RetVal"); Assert.Equal(3, retVal); } [Fact] public void Issue524_QueryMultiple_Cast() { // aka: Read should work even if the data is a // using regular API Assert.Equal(42, connection.Query("select cast(42 as bigint)").Single()); Assert.Equal(42, connection.QuerySingle("select cast(42 as bigint)")); // using multi-reader API using (var reader = connection.QueryMultiple("select cast(42 as bigint); select cast(42 as bigint)")) { Assert.Equal(42, reader.Read().Single()); Assert.Equal(42, reader.ReadSingle()); } } [Fact] public void QueryMultipleFromClosed() { using (var conn = GetClosedConnection()) { using (var multi = conn.QueryMultiple("select 1; select 'abc';")) { Assert.Equal(1, multi.Read().Single()); Assert.Equal("abc", multi.Read().Single()); } Assert.Equal(ConnectionState.Closed, conn.State); } } [Fact] public void QueryMultiple2FromClosed() { using (var conn = GetClosedConnection()) { Assert.Equal(ConnectionState.Closed, conn.State); using (var multi = conn.QueryMultiple("select 1 select 2 select 3")) { Assert.Equal(1, multi.Read().Single()); Assert.Equal(2, multi.Read().Single()); // not reading 3 is intentional here } Assert.Equal(ConnectionState.Closed, conn.State); } } [Fact] public void SO35554284_QueryMultipleUntilConsumed() { using (var reader = connection.QueryMultiple("select 1 as Id; select 2 as Id; select 3 as Id;")) { var items = new List(); while (!reader.IsConsumed) { items.AddRange(reader.Read()); } Assert.Equal(3, items.Count); Assert.Equal(1, items[0].Id); Assert.Equal(2, items[1].Id); Assert.Equal(3, items[2].Id); } } [Fact] public void QueryMultipleInvalidFromClosed() { using (var conn = GetClosedConnection()) { Assert.ThrowsAny(() => conn.QueryMultiple("select gibberish")); Assert.Equal(ConnectionState.Closed, conn.State); } } [Fact] public void TestMultiSelectWithSomeEmptyGridsUnbuffered() => TestMultiSelectWithSomeEmptyGrids(false); [Fact] public void TestMultiSelectWithSomeEmptyGridsBuffered() => TestMultiSelectWithSomeEmptyGrids(true); private void TestMultiSelectWithSomeEmptyGrids(bool buffered) { using (var reader = connection.QueryMultiple("select 1; select 2 where 1 = 0; select 3 where 1 = 0; select 4;")) { var one = reader.Read(buffered: buffered).ToArray(); var two = reader.Read(buffered: buffered).ToArray(); var three = reader.Read(buffered: buffered).ToArray(); var four = reader.Read(buffered: buffered).ToArray(); try { // only returned four grids; expect a fifth read to fail reader.Read(buffered: buffered); throw new InvalidOperationException("this should not have worked!"); } catch (ObjectDisposedException ex) { // expected; success Assert.Equal("The reader has been disposed; this can happen after all data has been consumed\r\nObject name: 'Dapper.SqlMapper+GridReader'.", ex.Message); } Assert.Single(one); Assert.Equal(1, one[0]); Assert.Empty(two); Assert.Empty(three); Assert.Single(four); Assert.Equal(4, four[0]); } } [Fact] public void TypeBasedViaTypeMulti() { Type type = Common.GetSomeType(); dynamic first, second; using (var multi = connection.QueryMultiple("select @A as [A], @B as [B]; select @C as [A], @D as [B]", new { A = 123, B = "abc", C = 456, D = "def" })) { first = multi.Read(type).Single(); second = multi.Read(type).Single(); } Assert.Equal(((object)first).GetType(), type); int a = first.A; string b = first.B; Assert.Equal(123, a); Assert.Equal("abc", b); Assert.Equal(((object)second).GetType(), type); a = second.A; b = second.B; Assert.Equal(456, a); Assert.Equal("def", b); } } }