diff --git a/.gitignore b/.gitignore index 62b03a5ac2ff230ecf7613800002719574dcb527..b01c6b033eb4950d49eae1ff871193e8fa78c664 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ NuGet.exe *.nupkg .docstats *.ide/ -*.lock.json \ No newline at end of file +*.lock.json +*.coverage \ No newline at end of file diff --git a/Dapper.DNX.Tests/Assert.cs b/Dapper.DNX.Tests/Assert.cs index fc854b3bb69f407e8215b6425e23cdf71f1244c3..8332f13aa443041adb2de49f1e9d3de1fc20f688 100644 --- a/Dapper.DNX.Tests/Assert.cs +++ b/Dapper.DNX.Tests/Assert.cs @@ -1,10 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; - -#if DOTNET5_2 -using ApplicationException = System.InvalidOperationException; -#endif namespace SqlMapper { @@ -13,54 +8,36 @@ static class Assert public static void IsEqualTo(this T obj, T other) { - if (!Equals(obj, other)) - { - throw new ApplicationException($"{obj} should be equals to {other}"); - } + Xunit.Assert.Equal(obj, other); } public static void IsSequenceEqualTo(this IEnumerable obj, IEnumerable other) { - if (!(obj ?? new T[0]).SequenceEqual(other ?? new T[0])) - { - throw new ApplicationException($"{obj} should be equals to {other}"); - } + Xunit.Assert.Equal(obj ?? new T[0], other); } public static void Fail() { - throw new ApplicationException("Expectation failed"); + Xunit.Assert.True(false, "Expectation failed"); } public static void IsFalse(this bool b) { - if (b) - { - throw new ApplicationException("Expected false"); - } + Xunit.Assert.False(b); } public static void IsTrue(this bool b) { - if (!b) - { - throw new ApplicationException("Expected true"); - } + Xunit.Assert.True(b); } public static void IsNull(this object obj) { - if (obj != null) - { - throw new ApplicationException("Expected null"); - } + Xunit.Assert.Null(obj); } public static void IsNotNull(this object obj) { - if (obj == null) - { - throw new ApplicationException("Expected not null"); - } + Xunit.Assert.NotNull(obj); } } } diff --git a/Dapper.DNX.Tests/Dapper.DNX.Tests.xproj b/Dapper.DNX.Tests/Dapper.DNX.Tests.xproj index 8a27427cd9c9c6c957af63fd16a46829b78073f3..53b76ff7071ec75ce873ee019940d456bbd1123c 100644 --- a/Dapper.DNX.Tests/Dapper.DNX.Tests.xproj +++ b/Dapper.DNX.Tests/Dapper.DNX.Tests.xproj @@ -17,5 +17,8 @@ True + + + \ No newline at end of file diff --git a/Dapper.DNX.Tests/Program.cs b/Dapper.DNX.Tests/Program.cs index 87cb6c8a1d5cdc45a4f44c47ccd681909403449d..12db0154d7ec314375133969517e8cef9390da24 100644 --- a/Dapper.DNX.Tests/Program.cs +++ b/Dapper.DNX.Tests/Program.cs @@ -171,7 +171,7 @@ insert Posts ([Text],CreationDate, LastChangeDate) values (replicate('x', 2000), #endif } - private static void RunTests(ref int fail, ref int skip, ref int pass, ref int frameworkFail, List failNames) where T : class, new() + private static void RunTests(ref int fail, ref int skip, ref int pass, ref int frameworkFail, List failNames) where T : class, IDisposable, new() { var tester = new T(); using (tester as IDisposable) @@ -193,7 +193,10 @@ private static void RunTests(ref int fail, ref int skip, ref int pass, ref in Console.Write("Running " + method.Name); try { - method.Invoke(tester, null); + using (var t = new T()) + { + method.Invoke(t, null); + } if (expectFrameworkFail) { Console.WriteLine(" - was expected to framework-fail, but didn't"); diff --git a/Dapper.DNX.Tests/Tests.Async.cs b/Dapper.DNX.Tests/Tests.Async.cs index 7e3ed1a404a5c2ffdc58c5b80ee13bbeee6ceabe..69e4389614f8748116e30e91a2725ba9448c0d82 100644 --- a/Dapper.DNX.Tests/Tests.Async.cs +++ b/Dapper.DNX.Tests/Tests.Async.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using System.Threading; using System.Data.SqlClient; +using Xunit; #if DOTNET5_2 using IDbConnection = System.Data.Common.DbConnection; @@ -15,27 +16,33 @@ namespace DapperTests_NET45 { - public class Tests + public class Tests : IDisposable { - public void TestBasicStringUsageAsync() + public void Dispose() { } + + [Fact] + public async Task TestBasicStringUsageAsync() { using (var connection = Program.GetOpenConnection()) { - var query = connection.QueryAsync("select 'abc' as [Value] union all select @txt", new { txt = "def" }); - var arr = query.Result.ToArray(); + var query = await connection.QueryAsync("select 'abc' as [Value] union all select @txt", new { txt = "def" }); + var arr = query.ToArray(); arr.IsSequenceEqualTo(new[] { "abc", "def" }); } } - public void TestBasicStringUsageAsyncNonBuffered() + + [Fact] + public async Task TestBasicStringUsageAsyncNonBuffered() { using (var connection = Program.GetOpenConnection()) { - var query = connection.QueryAsync(new CommandDefinition("select 'abc' as [Value] union all select @txt", new { txt = "def" }, flags: CommandFlags.None)); - var arr = query.Result.ToArray(); + var query = await connection.QueryAsync(new CommandDefinition("select 'abc' as [Value] union all select @txt", new { txt = "def" }, flags: CommandFlags.None)); + var arr = query.ToArray(); arr.IsSequenceEqualTo(new[] { "abc", "def" }); } } + [Fact] public void TestLongOperationWithCancellation() { using (var connection = Program.GetClosedConnection()) @@ -56,45 +63,50 @@ public void TestLongOperationWithCancellation() } } - public void TestBasicStringUsageClosedAsync() + [Fact] + public async Task TestBasicStringUsageClosedAsync() { using (var connection = Program.GetClosedConnection()) { - var query = connection.QueryAsync("select 'abc' as [Value] union all select @txt", new { txt = "def" }); - var arr = query.Result.ToArray(); + var query = await connection.QueryAsync("select 'abc' as [Value] union all select @txt", new { txt = "def" }); + var arr = query.ToArray(); arr.IsSequenceEqualTo(new[] { "abc", "def" }); } } - public void TestQueryDynamicAsync() + [Fact] + public async Task TestQueryDynamicAsync() { using (var connection = Program.GetClosedConnection()) { - var row = connection.QueryAsync("select 'abc' as [Value]").Result.Single(); + var row = (await connection.QueryAsync("select 'abc' as [Value]")).Single(); string value = row.Value; value.IsEqualTo("abc"); } } - public void TestClassWithStringUsageAsync() + [Fact] + public async Task TestClassWithStringUsageAsync() { using (var connection = Program.GetOpenConnection()) { - var query = connection.QueryAsync("select 'abc' as [Value] union all select @txt", new { txt = "def" }); - var arr = query.Result.ToArray(); + var query = await connection.QueryAsync("select 'abc' as [Value] union all select @txt", new { txt = "def" }); + var arr = query.ToArray(); arr.Select(x => x.Value).IsSequenceEqualTo(new[] { "abc", "def" }); } } - public void TestExecuteAsync() + [Fact] + public async Task TestExecuteAsync() { using (var connection = Program.GetOpenConnection()) { - var query = connection.ExecuteAsync("declare @foo table(id int not null); insert @foo values(@id);", new { id = 1 }); - var val = query.Result; + var val = await connection.ExecuteAsync("declare @foo table(id int not null); insert @foo values(@id);", new { id = 1 }); val.Equals(1); } } + + [Fact] public void TestExecuteClosedConnAsync() { using (var connection = Program.GetClosedConnection()) @@ -105,18 +117,19 @@ public void TestExecuteClosedConnAsync() } } - public void TestMultiMapWithSplitAsync() + [Fact] + public async Task TestMultiMapWithSplitAsync() { - var sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; + const string sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; using (var connection = Program.GetOpenConnection()) { - var productQuery = connection.QueryAsync(sql, (prod, cat) => + var productQuery = await connection.QueryAsync(sql, (prod, cat) => { prod.Category = cat; return prod; }); - var product = productQuery.Result.First(); + var product = productQuery.First(); // assertions product.Id.IsEqualTo(1); product.Name.IsEqualTo("abc"); @@ -125,16 +138,18 @@ public void TestMultiMapWithSplitAsync() } } - public void TestMultiMapArbitraryWithSplitAsync() { - var sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; + [Fact] + public async Task TestMultiMapArbitraryWithSplitAsync() + { + const string sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; using (var connection = Program.GetOpenConnection()) { - var productQuery = connection.QueryAsync(sql, new[] { typeof(Product), typeof(Category) }, (objects) => { + var productQuery = await connection.QueryAsync(sql, new[] { typeof(Product), typeof(Category) }, (objects) => { var prod = (Product)objects[0]; prod.Category = (Category)objects[1]; return prod; }); - var product = productQuery.Result.First(); + var product = productQuery.First(); // assertions product.Id.IsEqualTo(1); product.Name.IsEqualTo("abc"); @@ -143,18 +158,19 @@ public void TestMultiMapWithSplitAsync() } } - public void TestMultiMapWithSplitClosedConnAsync() + [Fact] + public async Task TestMultiMapWithSplitClosedConnAsync() { var sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; using (var connection = Program.GetClosedConnection()) { - var productQuery = connection.QueryAsync(sql, (prod, cat) => + var productQuery = await connection.QueryAsync(sql, (prod, cat) => { prod.Category = cat; return prod; }); - var product = productQuery.Result.First(); + var product = productQuery.First(); // assertions product.Id.IsEqualTo(1); product.Name.IsEqualTo("abc"); @@ -163,35 +179,40 @@ public void TestMultiMapWithSplitClosedConnAsync() } } - public void TestMultiAsync() + [Fact] + public async Task TestMultiAsync() { using (var conn = Program.GetOpenConnection()) { - using (Dapper.SqlMapper.GridReader multi = conn.QueryMultipleAsync("select 1; select 2").Result) + using (Dapper.SqlMapper.GridReader multi = await conn.QueryMultipleAsync("select 1; select 2")) { multi.ReadAsync().Result.Single().IsEqualTo(1); multi.ReadAsync().Result.Single().IsEqualTo(2); } } } - public void TestMultiClosedConnAsync() + + [Fact] + public async Task TestMultiClosedConnAsync() { using (var conn = Program.GetClosedConnection()) { - using (Dapper.SqlMapper.GridReader multi = conn.QueryMultipleAsync("select 1; select 2").Result) + using (Dapper.SqlMapper.GridReader multi = await conn.QueryMultipleAsync("select 1; select 2")) { multi.ReadAsync().Result.Single().IsEqualTo(1); multi.ReadAsync().Result.Single().IsEqualTo(2); } } } + #if EXTERNALS - public void ExecuteReaderOpenAsync() + [Fact] + public async Task ExecuteReaderOpenAsync() { using (var conn = Program.GetOpenConnection()) { var dt = new DataTable(); - dt.Load(conn.ExecuteReaderAsync("select 3 as [three], 4 as [four]").Result); + dt.Load(await conn.ExecuteReaderAsync("select 3 as [three], 4 as [four]")); dt.Columns.Count.IsEqualTo(2); dt.Columns[0].ColumnName.IsEqualTo("three"); dt.Columns[1].ColumnName.IsEqualTo("four"); @@ -200,12 +221,14 @@ public void ExecuteReaderOpenAsync() ((int)dt.Rows[0][1]).IsEqualTo(4); } } - public void ExecuteReaderClosedAsync() + + [Fact] + public async Task ExecuteReaderClosedAsync() { using (var conn = Program.GetClosedConnection()) { var dt = new DataTable(); - dt.Load(conn.ExecuteReaderAsync("select 3 as [three], 4 as [four]").Result); + dt.Load(await conn.ExecuteReaderAsync("select 3 as [three], 4 as [four]")); dt.Columns.Count.IsEqualTo(2); dt.Columns[0].ColumnName.IsEqualTo("three"); dt.Columns[1].ColumnName.IsEqualTo("four"); @@ -216,89 +239,96 @@ public void ExecuteReaderClosedAsync() } #endif - public void LiteralReplacementOpen() + [Fact] + public async Task LiteralReplacementOpen() { - using (var conn = Program.GetOpenConnection()) LiteralReplacement(conn); + using (var conn = Program.GetOpenConnection()) await LiteralReplacement(conn); } - public void LiteralReplacementClosed() + [Fact] + public async Task LiteralReplacementClosed() { - using (var conn = Program.GetClosedConnection()) LiteralReplacement(conn); + using (var conn = Program.GetClosedConnection()) await LiteralReplacement(conn); } - private void LiteralReplacement(IDbConnection connection) + private async Task LiteralReplacement(IDbConnection connection) { - try { connection.ExecuteAsync("drop table literal1").Wait(); } catch { } - connection.ExecuteAsync("create table literal1 (id int not null, foo int not null)").Wait(); - connection.ExecuteAsync("insert literal1 (id,foo) values ({=id}, @foo)", new { id = 123, foo = 456 }).Wait(); + try + { + await connection.ExecuteAsync("drop table literal1"); + } catch { } + await connection.ExecuteAsync("create table literal1 (id int not null, foo int not null)"); + await connection.ExecuteAsync("insert literal1 (id,foo) values ({=id}, @foo)", new { id = 123, foo = 456 }); var rows = new[] { new { id = 1, foo = 2 }, new { id = 3, foo = 4 } }; - connection.ExecuteAsync("insert literal1 (id,foo) values ({=id}, @foo)", rows).Wait(); - var count = connection.QueryAsync("select count(1) from literal1 where id={=foo}", new { foo = 123 }).Result.Single(); + await connection.ExecuteAsync("insert literal1 (id,foo) values ({=id}, @foo)", rows); + var count = (await connection.QueryAsync("select count(1) from literal1 where id={=foo}", new { foo = 123 })).Single(); count.IsEqualTo(1); - int sum = connection.QueryAsync("select sum(id) + sum(foo) from literal1").Result.Single(); + int sum = (await connection.QueryAsync("select sum(id) + sum(foo) from literal1")).Single(); sum.IsEqualTo(123 + 456 + 1 + 2 + 3 + 4); } - public void LiteralReplacementDynamicOpen() + [Fact] + public async Task LiteralReplacementDynamicOpen() { - using (var conn = Program.GetOpenConnection()) LiteralReplacementDynamic(conn); + using (var conn = Program.GetOpenConnection()) await LiteralReplacementDynamic(conn); } - public void LiteralReplacementDynamicClosed() + [Fact] + public async Task LiteralReplacementDynamicClosed() { - using (var conn = Program.GetClosedConnection()) LiteralReplacementDynamic(conn); + using (var conn = Program.GetClosedConnection()) await LiteralReplacementDynamic(conn); } - private void LiteralReplacementDynamic(IDbConnection connection) + private async Task LiteralReplacementDynamic(IDbConnection connection) { var args = new DynamicParameters(); args.Add("id", 123); - try { connection.ExecuteAsync("drop table literal2").Wait(); } catch { } - connection.ExecuteAsync("create table literal2 (id int not null)").Wait(); - connection.ExecuteAsync("insert literal2 (id) values ({=id})", args).Wait(); + try { await connection.ExecuteAsync("drop table literal2"); } catch { } + await connection.ExecuteAsync("create table literal2 (id int not null)"); + await connection.ExecuteAsync("insert literal2 (id) values ({=id})", args); args = new DynamicParameters(); args.Add("foo", 123); - var count = connection.QueryAsync("select count(1) from literal2 where id={=foo}", args).Result.Single(); + var count = (await connection.QueryAsync("select count(1) from literal2 where id={=foo}", args)).Single(); count.IsEqualTo(1); } - public void LiteralIn() + [Fact] + public async Task LiteralIn() { using (var connection = Program.GetOpenConnection()) { - connection.ExecuteAsync("create table #literalin(id int not null);").Wait(); - connection.ExecuteAsync("insert #literalin (id) values (@id)", new[] { + await connection.ExecuteAsync("create table #literalin(id int not null);"); + await connection.ExecuteAsync("insert #literalin (id) values (@id)", new[] { new { id = 1 }, new { id = 2 }, new { id = 3 }, - }).Wait(); - var count = connection.QueryAsync("select count(1) from #literalin where id in {=ids}", - new { ids = new[] { 1, 3, 4 } }).Result.Single(); + }); + var count = (await connection.QueryAsync("select count(1) from #literalin where id in {=ids}", + new { ids = new[] { 1, 3, 4 } })).Single(); count.IsEqualTo(2); } } - - public void RunSequentialVersusParallelAsync() + [Fact] + public async Task RunSequentialVersusParallelAsync() { - var ids = Enumerable.Range(1, 20000).Select(id => new { id }).ToArray(); using (var connection = Program.GetOpenConnection(true)) { - connection.ExecuteAsync(new CommandDefinition("select @id", ids.Take(5), flags: CommandFlags.None)).Wait(); + await connection.ExecuteAsync(new CommandDefinition("select @id", ids.Take(5), flags: CommandFlags.None)); var watch = Stopwatch.StartNew(); - connection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.None)).Wait(); + await connection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.None)); watch.Stop(); - System.Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds); + Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); - connection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined)).Wait(); + await connection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined)); watch.Stop(); - System.Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); + Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); } } + [Fact] public void RunSequentialVersusParallelSync() { - var ids = Enumerable.Range(1, 20000).Select(id => new { id }).ToArray(); using (var connection = Program.GetOpenConnection(true)) { @@ -307,15 +337,16 @@ public void RunSequentialVersusParallelSync() var watch = Stopwatch.StartNew(); connection.Execute(new CommandDefinition("select @id", ids, flags: CommandFlags.None)); watch.Stop(); - System.Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds); + Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); connection.Execute(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined)); watch.Stop(); - System.Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); + Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); } } + [Fact] public void AssertNoCacheWorksForQueryMultiple() { int a = 123, b = 456; @@ -340,8 +371,6 @@ public void AssertNoCacheWorksForQueryMultiple() after.IsEqualTo(0); c.IsEqualTo(123); d.IsEqualTo(456); - - } class Product { @@ -355,20 +384,20 @@ class Category public string Name { get; set; } public string Description { get; set; } } - + class BasicType { public string Value { get; set; } } - - public void TypeBasedViaType() + [Fact] + public async Task TypeBasedViaType() { Type type = GetSomeType(); using (var connection = Program.GetOpenConnection(true)) { - dynamic actual = connection.QueryAsync(type, "select @A as [A], @B as [B]", new { A = 123, B = "abc" }).Result.FirstOrDefault(); + dynamic actual = (await connection.QueryAsync(type, "select @A as [A], @B as [B]", new { A = 123, B = "abc" })).FirstOrDefault(); ((object)actual).GetType().IsEqualTo(type); int a = actual.A; string b = actual.B; @@ -387,37 +416,40 @@ public class SomeType public string B { get; set; } } - public void Issue22_ExecuteScalar() + [Fact] + public async Task Issue22_ExecuteScalar() { using (var connection = Program.GetOpenConnection()) { - int i = connection.ExecuteScalarAsync("select 123").Result; + int i = await connection.ExecuteScalarAsync("select 123"); i.IsEqualTo(123); - i = connection.ExecuteScalarAsync("select cast(123 as bigint)").Result; + i = await connection.ExecuteScalarAsync("select cast(123 as bigint)"); i.IsEqualTo(123); - long j = connection.ExecuteScalarAsync("select 123").Result; + long j = await connection.ExecuteScalarAsync("select 123"); j.IsEqualTo(123L); - j = connection.ExecuteScalarAsync("select cast(123 as bigint)").Result; + j = await connection.ExecuteScalarAsync("select cast(123 as bigint)"); j.IsEqualTo(123L); - int? k = connection.ExecuteScalar("select @i", new { i = default(int?) }); + int? k = await connection.ExecuteScalarAsync("select @i", new { i = default(int?) }); k.IsNull(); } } - public void Issue346_QueryAsyncConvert() + [Fact] + public async Task Issue346_QueryAsyncConvert() { using (var connection = Program.GetOpenConnection()) { - int i = connection.QueryAsync("Select Cast(123 as bigint)").Result.First(); + int i = (await connection.QueryAsync("Select Cast(123 as bigint)")).First(); i.IsEqualTo(123); } } - public void TestSupportForDynamicParametersOutputExpressions() + [Fact] + public async Task TestSupportForDynamicParametersOutputExpressions() { using (var connection = Program.GetOpenConnection()) { @@ -430,12 +462,12 @@ public void TestSupportForDynamicParametersOutputExpressions() p.Output(bob, b => b.Address.Name); p.Output(bob, b => b.Address.PersonId); - connection.ExecuteAsync(@" + await connection.ExecuteAsync(@" SET @Occupation = 'grillmaster' SET @PersonId = @PersonId + 1 SET @NumberOfLegs = @NumberOfLegs - 1 SET @AddressName = 'bobs burgers' -SET @AddressPersonId = @PersonId", p).Wait(); +SET @AddressPersonId = @PersonId", p); bob.Occupation.IsEqualTo("grillmaster"); bob.PersonId.IsEqualTo(2); @@ -444,7 +476,9 @@ public void TestSupportForDynamicParametersOutputExpressions() bob.Address.PersonId.IsEqualTo(2); } } - public void TestSupportForDynamicParametersOutputExpressions_Scalar() + + [Fact] + public async Task TestSupportForDynamicParametersOutputExpressions_Scalar() { using (var connection = Program.GetOpenConnection()) { @@ -457,13 +491,13 @@ public void TestSupportForDynamicParametersOutputExpressions_Scalar() p.Output(bob, b => b.Address.Name); p.Output(bob, b => b.Address.PersonId); - var result = (int)connection.ExecuteScalarAsync(@" + var result = (int)(await connection.ExecuteScalarAsync(@" SET @Occupation = 'grillmaster' SET @PersonId = @PersonId + 1 SET @NumberOfLegs = @NumberOfLegs - 1 SET @AddressName = 'bobs burgers' SET @AddressPersonId = @PersonId -select 42", p).Result; +select 42", p)); bob.Occupation.IsEqualTo("grillmaster"); bob.PersonId.IsEqualTo(2); @@ -473,7 +507,9 @@ public void TestSupportForDynamicParametersOutputExpressions_Scalar() result.IsEqualTo(42); } } - public void TestSupportForDynamicParametersOutputExpressions_Query_Default() + + [Fact] + public async Task TestSupportForDynamicParametersOutputExpressions_Query_Default() { using (var connection = Program.GetOpenConnection()) { @@ -486,13 +522,13 @@ public void TestSupportForDynamicParametersOutputExpressions_Query_Default() p.Output(bob, b => b.Address.Name); p.Output(bob, b => b.Address.PersonId); - var result = connection.QueryAsync(@" + var result = (await connection.QueryAsync(@" SET @Occupation = 'grillmaster' SET @PersonId = @PersonId + 1 SET @NumberOfLegs = @NumberOfLegs - 1 SET @AddressName = 'bobs burgers' SET @AddressPersonId = @PersonId -select 42", p).Result.Single(); +select 42", p)).Single(); bob.Occupation.IsEqualTo("grillmaster"); bob.PersonId.IsEqualTo(2); @@ -502,7 +538,9 @@ public void TestSupportForDynamicParametersOutputExpressions_Query_Default() result.IsEqualTo(42); } } - public void TestSupportForDynamicParametersOutputExpressions_Query_Buffered() + + [Fact] + public async Task TestSupportForDynamicParametersOutputExpressions_Query_Buffered() { using (var connection = Program.GetOpenConnection()) { @@ -515,13 +553,13 @@ public void TestSupportForDynamicParametersOutputExpressions_Query_Buffered() p.Output(bob, b => b.Address.Name); p.Output(bob, b => b.Address.PersonId); - var result = connection.QueryAsync(new CommandDefinition(@" + var result = (await connection.QueryAsync(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(); +select 42", p, flags: CommandFlags.Buffered))).Single(); bob.Occupation.IsEqualTo("grillmaster"); bob.PersonId.IsEqualTo(2); @@ -531,7 +569,9 @@ public void TestSupportForDynamicParametersOutputExpressions_Query_Buffered() result.IsEqualTo(42); } } - public void TestSupportForDynamicParametersOutputExpressions_Query_NonBuffered() + + [Fact] + public async Task TestSupportForDynamicParametersOutputExpressions_Query_NonBuffered() { using (var connection = Program.GetOpenConnection()) { @@ -544,13 +584,13 @@ public void TestSupportForDynamicParametersOutputExpressions_Query_NonBuffered() p.Output(bob, b => b.Address.Name); p.Output(bob, b => b.Address.PersonId); - var result = connection.QueryAsync(new CommandDefinition(@" + var result = (await connection.QueryAsync(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(); +select 42", p, flags: CommandFlags.None))).Single(); bob.Occupation.IsEqualTo("grillmaster"); bob.PersonId.IsEqualTo(2); @@ -560,7 +600,9 @@ public void TestSupportForDynamicParametersOutputExpressions_Query_NonBuffered() result.IsEqualTo(42); } } - public void TestSupportForDynamicParametersOutputExpressions_QueryMultiple() + + [Fact] + public async Task TestSupportForDynamicParametersOutputExpressions_QueryMultiple() { using (var connection = Program.GetOpenConnection()) { @@ -574,14 +616,14 @@ public void TestSupportForDynamicParametersOutputExpressions_QueryMultiple() p.Output(bob, b => b.Address.PersonId); int x, y; - using (var multi = connection.QueryMultipleAsync(@" + using (var multi = await 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) +SET @AddressPersonId = @PersonId", p)) { x = multi.ReadAsync().Result.Single(); y = multi.ReadAsync().Result.Single(); @@ -597,27 +639,28 @@ select 17 } } - public void TestSubsequentQueriesSuccess() + [Fact] + public async Task TestSubsequentQueriesSuccess() { using (var connection = Program.GetOpenConnection()) { - var data0 = connection.QueryAsync("select 1 as [Id] where 1 = 0").Result.ToList(); - data0.Count().IsEqualTo(0); + var data0 = (await connection.QueryAsync("select 1 as [Id] where 1 = 0")).ToList(); + data0.Count.IsEqualTo(0); - var data1 = connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered)).Result.ToList(); - data1.Count().IsEqualTo(0); + var data1 = (await connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered))).ToList(); + data1.Count.IsEqualTo(0); - var data2 = connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None)).Result.ToList(); - data2.Count().IsEqualTo(0); + var data2 = (await connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None))).ToList(); + data2.Count.IsEqualTo(0); - data0 = connection.QueryAsync("select 1 as [Id] where 1 = 0").Result.ToList(); - data0.Count().IsEqualTo(0); + data0 = (await connection.QueryAsync("select 1 as [Id] where 1 = 0")).ToList(); + data0.Count.IsEqualTo(0); - data1 = connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered)).Result.ToList(); - data1.Count().IsEqualTo(0); + data1 = (await connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered))).ToList(); + data1.Count.IsEqualTo(0); - data2 = connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None)).Result.ToList(); - data2.Count().IsEqualTo(0); + data2 = (await connection.QueryAsync(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None))).ToList(); + data2.Count.IsEqualTo(0); } } @@ -659,10 +702,11 @@ class User public string Name { get; set; } } - public void TestMultiMapArbitraryMaps() + [Fact] + public async Task TestMultiMapArbitraryMaps() { // please excuse the trite example, but it is easier to follow than a more real-world one - var createSql = @" + const string createSql = @" create table #ReviewBoards (Id int, Name varchar(20), User1Id int, User2Id int, User3Id int, User4Id int, User5Id int, User6Id int, User7Id int, User8Id int, User9Id int) create table #Users (Id int, Name varchar(20)) @@ -680,10 +724,10 @@ public void TestMultiMapArbitraryMaps() "; using (var connection = Program.GetOpenConnection()) { - connection.ExecuteAsync(createSql).Wait(); + await connection.ExecuteAsync(createSql); try { - var sql = @" + const string sql = @" select rb.Id, rb.Name, u1.*, u2.*, u3.*, u4.*, u5.*, u6.*, u7.*, u8.*, u9.* @@ -716,7 +760,7 @@ public void TestMultiMapArbitraryMaps() return board; }; - var data = connection.QueryAsync(sql, types, mapper).Result.ToList(); + var data = (await connection.QueryAsync(sql, types, mapper)).ToList(); var p = data.First(); p.Id.IsEqualTo(1); @@ -748,33 +792,35 @@ public void TestMultiMapArbitraryMaps() } } - public void Issue157_ClosedReaderAsync() + [Fact] + public async Task Issue157_ClosedReaderAsync() { using(var conn = Program.GetOpenConnection()) { var args = new { x = 42 }; const string sql = @"select 123 as [A], 'abc' as [B] where @x=42"; - var row = conn.QueryAsync(new CommandDefinition( - sql, args, flags:CommandFlags.None)).Result.Single(); + var row = (await conn.QueryAsync(new CommandDefinition( + sql, args, flags:CommandFlags.None))).Single(); row.IsNotNull(); row.A.IsEqualTo(123); row.B.IsEqualTo("abc"); args = new { x = 5 }; - conn.QueryAsync(new CommandDefinition( - sql, args, flags: CommandFlags.None)).Result.Any().IsFalse(); + (await conn.QueryAsync(new CommandDefinition( + sql, args, flags: CommandFlags.None))).Any().IsFalse(); } } - public void TestAtEscaping() + [Fact] + public async Task TestAtEscaping() { using (var connection = Program.GetOpenConnection()) { - var id = connection.QueryAsync(@" + var id = (await connection.QueryAsync(@" declare @@Name int select @@Name = @Id+1 select @@Name - ", new Product { Id = 1 }).Result.Single(); + ", new Product { Id = 1 })).Single(); id.IsEqualTo(2); } diff --git a/Dapper.DNX.Tests/Tests.Constructors.cs b/Dapper.DNX.Tests/Tests.Constructors.cs new file mode 100644 index 0000000000000000000000000000000000000000..b8f6c9603e310cea98f25826d593094c9084ef11 --- /dev/null +++ b/Dapper.DNX.Tests/Tests.Constructors.cs @@ -0,0 +1,227 @@ +using Dapper; +using System; +using System.Data; +using System.Linq; +using Xunit; + +#if DOTNET5_2 +using IDbCommand = System.Data.Common.DbCommand; +using IDbDataParameter = System.Data.Common.DbParameter; +using IDbConnection = System.Data.Common.DbConnection; +using IDbTransaction = System.Data.Common.DbTransaction; +using IDataReader = System.Data.Common.DbDataReader; +#endif + +namespace SqlMapper +{ + public partial class Tests + { + [Fact] + public void TestAbstractInheritance() + { + var order = connection.Query("select 1 Internal,2 Protected,3 [Public],4 Concrete").First(); + + order.Internal.IsEqualTo(1); + order.ProtectedVal.IsEqualTo(2); + order.Public.IsEqualTo(3); + order.Concrete.IsEqualTo(4); + } + + [Fact] + public void TestMultipleConstructors() + { + MultipleConstructors mult = connection.Query("select 0 A, 'Dapper' b").First(); + mult.A.IsEqualTo(0); + mult.B.IsEqualTo("Dapper"); + } + + [Fact] + public void TestConstructorsWithAccessModifiers() + { + ConstructorsWithAccessModifiers value = connection.Query("select 0 A, 'Dapper' b").First(); + value.A.IsEqualTo(1); + value.B.IsEqualTo("Dapper!"); + } + + + [Fact] + public void TestNoDefaultConstructor() + { + var guid = Guid.NewGuid(); + NoDefaultConstructor nodef = connection.Query("select CAST(NULL AS integer) A1, CAST(NULL AS integer) b1, CAST(NULL AS real) f1, 'Dapper' s1, G1 = @id", new { id = guid }).First(); + nodef.A.IsEqualTo(0); + nodef.B.IsEqualTo(null); + nodef.F.IsEqualTo(0); + nodef.S.IsEqualTo("Dapper"); + nodef.G.IsEqualTo(guid); + } + + [Fact] + public void TestNoDefaultConstructorWithChar() + { + const char c1 = 'ą'; + const char c3 = 'ó'; + NoDefaultConstructorWithChar nodef = connection.Query("select @c1 c1, @c2 c2, @c3 c3", new { c1 = c1, c2 = (char?)null, c3 = c3 }).First(); + nodef.Char1.IsEqualTo(c1); + nodef.Char2.IsEqualTo(null); + nodef.Char3.IsEqualTo(c3); + } + + + [Fact] + public void TestNoDefaultConstructorWithEnum() + { + NoDefaultConstructorWithEnum nodef = connection.Query("select cast(2 as smallint) E1, cast(5 as smallint) n1, cast(null as smallint) n2").First(); + nodef.E.IsEqualTo(ShortEnum.Two); + nodef.NE1.IsEqualTo(ShortEnum.Five); + nodef.NE2.IsEqualTo(null); + } + + [Fact] + public void ExplicitConstructors() + { + var rows = connection.Query<_ExplicitConstructors>(@" +declare @ExplicitConstructors table ( + Field INT NOT NULL PRIMARY KEY IDENTITY(1,1), + Field_1 INT NOT NULL); +insert @ExplicitConstructors(Field_1) values (1); +SELECT * FROM @ExplicitConstructors" +).ToList(); + + rows.Count.IsEqualTo(1); + rows[0].Field.IsEqualTo(1); + rows[0].Field_1.IsEqualTo(1); + rows[0].GetWentThroughProperConstructor().IsTrue(); + } + class _ExplicitConstructors + { + public int Field { get; set; } + public int Field_1 { get; set; } + + private bool WentThroughProperConstructor; + + public _ExplicitConstructors() { } + + [ExplicitConstructor] + public _ExplicitConstructors(string foo, int bar) + { + WentThroughProperConstructor = true; + } + + public bool GetWentThroughProperConstructor() + { + return WentThroughProperConstructor; + } + } + +#if EXTERNALS + class NoDefaultConstructorWithBinary + { + public System.Data.Linq.Binary Value { get; set; } + public int Ynt { get; set; } + public NoDefaultConstructorWithBinary(System.Data.Linq.Binary val) + { + Value = val; + } + } + [Fact] + public void TestNoDefaultConstructorBinary() + { + byte[] orig = new byte[20]; + new Random(123456).NextBytes(orig); + var input = new System.Data.Linq.Binary(orig); + var output = connection.Query("select @input as val", new { input }).First().Value; + output.ToArray().IsSequenceEqualTo(orig); + } +#endif + + public class AbstractInheritance + { + public abstract class Order + { + internal int Internal { get; set; } + protected int Protected { get; set; } + public int Public { get; set; } + + public int ProtectedVal => Protected; + } + + public class ConcreteOrder : Order + { + public int Concrete { get; set; } + } + } + + class MultipleConstructors + { + public MultipleConstructors() + { + + } + public MultipleConstructors(int a, string b) + { + A = a + 1; + B = b + "!"; + } + public int A { get; set; } + public string B { get; set; } + } + + class ConstructorsWithAccessModifiers + { + private ConstructorsWithAccessModifiers() + { + } + public ConstructorsWithAccessModifiers(int a, string b) + { + A = a + 1; + B = b + "!"; + } + public int A { get; set; } + public string B { get; set; } + } + + class NoDefaultConstructor + { + public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1) + { + A = a1; + B = b1; + F = f1; + S = s1; + G = G1; + } + public int A { get; set; } + public int? B { get; set; } + public float F { get; set; } + public string S { get; set; } + public Guid G { get; set; } + } + + class NoDefaultConstructorWithChar + { + public NoDefaultConstructorWithChar(char c1, char? c2, char? c3) + { + Char1 = c1; + Char2 = c2; + Char3 = c3; + } + public char Char1 { get; set; } + public char? Char2 { get; set; } + public char? Char3 { get; set; } + } + + class NoDefaultConstructorWithEnum + { + public NoDefaultConstructorWithEnum(ShortEnum e1, ShortEnum? n1, ShortEnum? n2) + { + E = e1; + NE1 = n1; + NE2 = n2; + } + public ShortEnum E { get; set; } + public ShortEnum? NE1 { get; set; } + public ShortEnum? NE2 { get; set; } + } + } +} diff --git a/Dapper.DNX.Tests/Tests.Enums.cs b/Dapper.DNX.Tests/Tests.Enums.cs new file mode 100644 index 0000000000000000000000000000000000000000..b86ea2ca4bac28fccaf4f1751d8aa9a80d88a5b9 --- /dev/null +++ b/Dapper.DNX.Tests/Tests.Enums.cs @@ -0,0 +1,92 @@ +using Dapper; +using System; +using System.Data; +using System.Linq; +using Xunit; + +#if DOTNET5_2 +using IDbCommand = System.Data.Common.DbCommand; +using IDbDataParameter = System.Data.Common.DbParameter; +using IDbConnection = System.Data.Common.DbConnection; +using IDbTransaction = System.Data.Common.DbTransaction; +using IDataReader = System.Data.Common.DbDataReader; +#endif + +namespace SqlMapper +{ + public partial class Tests + { + [Fact] + public void TestEnumWeirdness() + { + connection.Query("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null); + connection.Query("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); + } + + [Fact] + public void TestEnumStrings() + { + connection.Query("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); + connection.Query("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); + + connection.Query("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); + connection.Query("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); + } + + [Fact] + public void TestEnumParamsWithNullable() + { + EnumParam a = EnumParam.A; + EnumParam? b = EnumParam.B, c = null; + var obj = connection.Query("select @a as A, @b as B, @c as C", + new { a, b, c }).Single(); + obj.A.IsEqualTo(EnumParam.A); + obj.B.IsEqualTo(EnumParam.B); + obj.C.IsEqualTo(null); + } + + [Fact] + public void TestEnumParamsWithoutNullable() + { + EnumParam a = EnumParam.A; + EnumParam b = EnumParam.B, c = 0; + var obj = connection.Query("select @a as A, @b as B, @c as C", + new { a, b, c }).Single(); + obj.A.IsEqualTo(EnumParam.A); + obj.B.IsEqualTo(EnumParam.B); + obj.C.IsEqualTo((EnumParam)0); + } + enum EnumParam : short + { + None, A, B + } + class EnumParamObject + { + public EnumParam A { get; set; } + public EnumParam? B { get; set; } + public EnumParam? C { get; set; } + } + class EnumParamObjectNonNullable + { + public EnumParam A { get; set; } + public EnumParam? B { get; set; } + public EnumParam? C { get; set; } + } + + + + + enum TestEnum : byte + { + Bla = 1 + } + class TestEnumClass + { + public TestEnum? EnumEnum { get; set; } + } + class TestEnumClassNoNull + { + public TestEnum EnumEnum { get; set; } + } + } +} diff --git a/Dapper.DNX.Tests/Tests.MultiMap.cs b/Dapper.DNX.Tests/Tests.MultiMap.cs new file mode 100644 index 0000000000000000000000000000000000000000..857a19d87cb7219ecae7e095a28502112bfae2e7 --- /dev/null +++ b/Dapper.DNX.Tests/Tests.MultiMap.cs @@ -0,0 +1,616 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using Xunit; + +#if DOTNET5_2 +using IDbCommand = System.Data.Common.DbCommand; +using IDbDataParameter = System.Data.Common.DbParameter; +using IDbConnection = System.Data.Common.DbConnection; +using IDbTransaction = System.Data.Common.DbTransaction; +using IDataReader = System.Data.Common.DbDataReader; +#endif + +namespace SqlMapper +{ + public partial class Tests + { + [Fact] + public void ParentChildIdentityAssociations() + { + var lookup = new Dictionary(); + var parents = connection.Query(@"select 1 as [Id], 1 as [Id] union all select 1,2 union all select 2,3 union all select 1,4 union all select 3,5", + (parent, child) => + { + Parent found; + if (!lookup.TryGetValue(parent.Id, out found)) + { + lookup.Add(parent.Id, found = parent); + } + found.Children.Add(child); + return found; + }).Distinct().ToDictionary(p => p.Id); + parents.Count.IsEqualTo(3); + parents[1].Children.Select(c => c.Id).SequenceEqual(new[] { 1, 2, 4 }).IsTrue(); + parents[2].Children.Select(c => c.Id).SequenceEqual(new[] { 3 }).IsTrue(); + parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue(); + } + + class Parent + { + public int Id { get; set; } + public readonly List Children = new List(); + } + class Child + { + public int Id { get; set; } + } + + [Fact] + public void TestMultiMap() + { + var 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') +"; + connection.Execute(createSql); + try + { + var sql = + @"select * from #Posts p +left join #Users u on u.Id = p.OwnerId +Order by p.Id"; + + var data = connection.Query(sql, (post, user) => { post.Owner = user; return post; }).ToList(); + var p = data.First(); + + p.Content.IsEqualTo("Sams Post1"); + p.Id.IsEqualTo(1); + p.Owner.Name.IsEqualTo("Sam"); + p.Owner.Id.IsEqualTo(99); + + data[2].Owner.IsNull(); + } + finally + { + connection.Execute("drop table #Users drop table #Posts"); + } + } + + [Fact] + public void TestMultiMapThreeTypesWithGridReader() + { + var createSql = @" + create table #Users (Id int, Name varchar(20)) + create table #Posts (Id int, OwnerId int, Content varchar(20)) + create table #Comments (Id int, PostId int, CommentData 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') + + insert #Comments values(1, 1, 'Comment 1')"; + connection.Execute(createSql); + try + { + const string sql = @"SELECT p.* FROM #Posts p + +select p.*, u.Id, u.Name + '0' Name, c.Id, c.CommentData from #Posts p +left join #Users u on u.Id = p.OwnerId +left join #Comments c on c.PostId = p.Id +where p.Id = 1 +Order by p.Id"; + + var grid = connection.QueryMultiple(sql); + + var post1 = grid.Read().ToList(); + + var post2 = grid.Read((post, user, comment) => { post.Owner = user; post.Comment = comment; return post; }).SingleOrDefault(); + + post2.Comment.Id.IsEqualTo(1); + post2.Owner.Id.IsEqualTo(99); + + } + finally + { + connection.Execute("drop table #Users drop table #Posts drop table #Comments"); + } + } + + class User + { + public int Id { get; set; } + public string Name { get; set; } + } + class Post + { + public int Id { get; set; } + public User Owner { get; set; } + public string Content { get; set; } + public Comment Comment { get; set; } + } + class Comment + { + public int Id { get; set; } + public string CommentData { get; set; } + } + + [Fact] + public void TestMultiMapperIsNotConfusedWithUnorderedCols() + { + var result = connection.Query>("select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name", Tuple.Create, splitOn: "BarId").First(); + + result.Item1.Id.IsEqualTo(1); + result.Item1.BarId.IsEqualTo(2); + result.Item2.BarId.IsEqualTo(3); + result.Item2.Name.IsEqualTo("a"); + } + + class Foo1 + { +#pragma warning disable 0649 + public int Id; +#pragma warning restore 0649 + public int BarId { get; set; } + } + class Bar1 + { +#pragma warning disable 0649 + public int BarId; +#pragma warning restore 0649 + public string Name { get; set; } + } + + [Fact] + public void TestMultiMapDynamic() + { + var 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') +"; + connection.Execute(createSql); + + var sql = +@"select * from #Posts p +left join #Users u on u.Id = p.OwnerId +Order by p.Id"; + + var data = connection.Query(sql, (post, user) => { post.Owner = user; return post; }).ToList(); + var p = data.First(); + + // hairy extension method support for dynamics + ((string)p.Content).IsEqualTo("Sams Post1"); + ((int)p.Id).IsEqualTo(1); + ((string)p.Owner.Name).IsEqualTo("Sam"); + ((int)p.Owner.Id).IsEqualTo(99); + + ((object)data[2].Owner).IsNull(); + + connection.Execute("drop table #Users drop table #Posts"); + } + + [Fact] + public void TestMultiMapWithSplit() // http://stackoverflow.com/q/6056778/23354 + { + var sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; + var product = connection.Query(sql, (prod, cat) => + { + prod.Category = cat; + return prod; + }).First(); + // assertions + product.Id.IsEqualTo(1); + product.Name.IsEqualTo("abc"); + product.Category.Id.IsEqualTo(2); + product.Category.Name.IsEqualTo("def"); + } + + [Fact] + public void TestMultiMapWithSplitWithNullValue() // http://stackoverflow.com/q/10744728/449906 + { + var sql = @"select 1 as id, 'abc' as name, NULL as description, 'def' as name"; + var product = connection.Query(sql, (prod, cat) => + { + prod.Category = cat; + return prod; + }, splitOn: "description").First(); + // assertions + product.Id.IsEqualTo(1); + product.Name.IsEqualTo("abc"); + product.Category.IsNull(); + } + + [Fact] + public void TestMultiMapWithSplitWithNullValueAndSpoofColumn() // http://stackoverflow.com/q/10744728/449906 + { + var sql = @"select 1 as id, 'abc' as name, 1 as spoof, NULL as description, 'def' as name"; + var product = connection.Query(sql, (prod, cat) => + { + prod.Category = cat; + return prod; + }, splitOn: "spoof").First(); + // assertions + product.Id.IsEqualTo(1); + product.Name.IsEqualTo("abc"); + product.Category.IsNotNull(); + product.Category.Id.IsEqualTo(0); + product.Category.Name.IsEqualTo("def"); + product.Category.Description.IsNull(); + } + + class Product + { + public int Id { get; set; } + public string Name { get; set; } + public Category Category { get; set; } + } + class Category + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + + [Fact] + public void TestMultiMappingVariations() + { + var sql = @"select 1 as Id, 'a' as Content, 2 as Id, 'b' as Content, 3 as Id, 'c' as Content, 4 as Id, 'd' as Content, 5 as Id, 'e' as Content"; + + var order = connection.Query(sql, (o, owner, creator) => { o.Owner = owner; o.Creator = creator; return o; }).First(); + + Assert.IsEqualTo(order.Id, 1); + Assert.IsEqualTo(order.Content, "a"); + Assert.IsEqualTo(order.Owner.Id, 2); + Assert.IsEqualTo(order.Owner.Content, "b"); + Assert.IsEqualTo(order.Creator.Id, 3); + Assert.IsEqualTo(order.Creator.Content, "c"); + + order = connection.Query(sql, (o, owner, creator, address) => + { + o.Owner = owner; + o.Creator = creator; + o.Owner.Address = address; + return o; + }).First(); + + Assert.IsEqualTo(order.Id, 1); + Assert.IsEqualTo(order.Content, "a"); + Assert.IsEqualTo(order.Owner.Id, 2); + Assert.IsEqualTo(order.Owner.Content, "b"); + Assert.IsEqualTo(order.Creator.Id, 3); + Assert.IsEqualTo(order.Creator.Content, "c"); + Assert.IsEqualTo(order.Owner.Address.Id, 4); + Assert.IsEqualTo(order.Owner.Address.Content, "d"); + + order = connection.Query(sql, (a, b, c, d, e) => { a.B = b; a.C = c; a.C.D = d; a.E = e; return a; }).First(); + + Assert.IsEqualTo(order.Id, 1); + Assert.IsEqualTo(order.Content, "a"); + Assert.IsEqualTo(order.B.Id, 2); + Assert.IsEqualTo(order.B.Content, "b"); + Assert.IsEqualTo(order.C.Id, 3); + Assert.IsEqualTo(order.C.Content, "c"); + Assert.IsEqualTo(order.C.D.Id, 4); + Assert.IsEqualTo(order.C.D.Content, "d"); + Assert.IsEqualTo(order.E.Id, 5); + Assert.IsEqualTo(order.E.Content, "e"); + } + + class UserWithConstructor + { + public UserWithConstructor(int id, string name) + { + Ident = id; + FullName = name; + } + public int Ident { get; set; } + public string FullName { get; set; } + } + + class PostWithConstructor + { + public PostWithConstructor(int id, int ownerid, string content) + { + Ident = id; + FullContent = content; + } + + public int Ident { get; set; } + public UserWithConstructor Owner { get; set; } + public string FullContent { get; set; } + public Comment Comment { get; set; } + } + + [Fact] + public void TestMultiMapWithConstructor() + { + var 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')"; + connection.Execute(createSql); + try + { + string sql = @"select * from #Posts p + left join #Users u on u.Id = p.OwnerId + Order by p.Id"; + PostWithConstructor[] data = connection.Query(sql, (post, user) => { post.Owner = user; return post; }).ToArray(); + var p = data.First(); + + p.FullContent.IsEqualTo("Sams Post1"); + p.Ident.IsEqualTo(1); + p.Owner.FullName.IsEqualTo("Sam"); + p.Owner.Ident.IsEqualTo(99); + + data[2].Owner.IsNull(); + } + finally + { + connection.Execute("drop table #Users drop table #Posts"); + } + } + + class ReviewBoard + { + public int Id { get; set; } + public string Name { get; set; } + public User User1 { get; set; } + public User User2 { get; set; } + public User User3 { get; set; } + public User User4 { get; set; } + public User User5 { get; set; } + public User User6 { get; set; } + public User User7 { get; set; } + public User User8 { get; set; } + public User User9 { get; set; } + } + + [Fact] + public void TestMultiMapArbitraryMaps() + { + // please excuse the trite example, but it is easier to follow than a more real-world one + var createSql = @" + create table #ReviewBoards (Id int, Name varchar(20), User1Id int, User2Id int, User3Id int, User4Id int, User5Id int, User6Id int, User7Id int, User8Id int, User9Id int) + create table #Users (Id int, Name varchar(20)) + + insert #Users values(1, 'User 1') + insert #Users values(2, 'User 2') + insert #Users values(3, 'User 3') + insert #Users values(4, 'User 4') + insert #Users values(5, 'User 5') + insert #Users values(6, 'User 6') + insert #Users values(7, 'User 7') + insert #Users values(8, 'User 8') + insert #Users values(9, 'User 9') + + insert #ReviewBoards values(1, 'Review Board 1', 1, 2, 3, 4, 5, 6, 7, 8, 9) +"; + connection.Execute(createSql); + try + { + var sql = @" + select + rb.Id, rb.Name, + u1.*, u2.*, u3.*, u4.*, u5.*, u6.*, u7.*, u8.*, u9.* + from #ReviewBoards rb + inner join #Users u1 on u1.Id = rb.User1Id + inner join #Users u2 on u2.Id = rb.User2Id + inner join #Users u3 on u3.Id = rb.User3Id + inner join #Users u4 on u4.Id = rb.User4Id + inner join #Users u5 on u5.Id = rb.User5Id + inner join #Users u6 on u6.Id = rb.User6Id + inner join #Users u7 on u7.Id = rb.User7Id + inner join #Users u8 on u8.Id = rb.User8Id + inner join #Users u9 on u9.Id = rb.User9Id +"; + + var types = new[] { typeof(ReviewBoard), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User) }; + + Func mapper = (objects) => + { + var board = (ReviewBoard)objects[0]; + board.User1 = (User)objects[1]; + board.User2 = (User)objects[2]; + board.User3 = (User)objects[3]; + board.User4 = (User)objects[4]; + board.User5 = (User)objects[5]; + board.User6 = (User)objects[6]; + board.User7 = (User)objects[7]; + board.User8 = (User)objects[8]; + board.User9 = (User)objects[9]; + return board; + }; + + var data = connection.Query(sql, types, mapper).ToList(); + + var p = data.First(); + p.Id.IsEqualTo(1); + p.Name.IsEqualTo("Review Board 1"); + p.User1.Id.IsEqualTo(1); + p.User2.Id.IsEqualTo(2); + p.User3.Id.IsEqualTo(3); + p.User4.Id.IsEqualTo(4); + p.User5.Id.IsEqualTo(5); + p.User6.Id.IsEqualTo(6); + p.User7.Id.IsEqualTo(7); + p.User8.Id.IsEqualTo(8); + p.User9.Id.IsEqualTo(9); + p.User1.Name.IsEqualTo("User 1"); + p.User2.Name.IsEqualTo("User 2"); + p.User3.Name.IsEqualTo("User 3"); + p.User4.Name.IsEqualTo("User 4"); + p.User5.Name.IsEqualTo("User 5"); + p.User6.Name.IsEqualTo("User 6"); + p.User7.Name.IsEqualTo("User 7"); + p.User8.Name.IsEqualTo("User 8"); + p.User9.Name.IsEqualTo("User 9"); + } + finally + { + connection.Execute("drop table #Users drop table #ReviewBoards"); + } + } + + [Fact] + public void TestMultiMapGridReader() + { + var 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') +"; + connection.Execute(createSql); + + var sql = +@"select p.*, u.Id, u.Name + '0' Name from #Posts p +left join #Users u on u.Id = p.OwnerId +Order by p.Id + +select p.*, u.Id, u.Name + '1' Name from #Posts p +left join #Users u on u.Id = p.OwnerId +Order by p.Id +"; + + var grid = connection.QueryMultiple(sql); + + for (int i = 0; i < 2; i++) + { + var data = grid.Read((post, user) => { post.Owner = user; return post; }).ToList(); + var p = data.First(); + + p.Content.IsEqualTo("Sams Post1"); + p.Id.IsEqualTo(1); + p.Owner.Name.IsEqualTo("Sam" + i); + p.Owner.Id.IsEqualTo(99); + + data[2].Owner.IsNull(); + } + + connection.Execute("drop table #Users drop table #Posts"); + } + + [Fact] + public void TestFlexibleMultiMapping() + { + var sql = +@"select + 1 as PersonId, 'bob' as Name, + 2 as AddressId, 'abc street' as Name, 1 as PersonId, + 3 as Id, 'fred' as Name + "; + var personWithAddress = connection.Query> + (sql, Tuple.Create, splitOn: "AddressId,Id").First(); + + personWithAddress.Item1.PersonId.IsEqualTo(1); + personWithAddress.Item1.Name.IsEqualTo("bob"); + personWithAddress.Item2.AddressId.IsEqualTo(2); + personWithAddress.Item2.Name.IsEqualTo("abc street"); + personWithAddress.Item2.PersonId.IsEqualTo(1); + personWithAddress.Item3.Id.IsEqualTo(3); + personWithAddress.Item3.Name.IsEqualTo("fred"); + } + + [Fact] + public void TestMultiMappingWithSplitOnSpaceBetweenCommas() + { + var sql = @"select + 1 as PersonId, 'bob' as Name, + 2 as AddressId, 'abc street' as Name, 1 as PersonId, + 3 as Id, 'fred' as Name + "; + var personWithAddress = connection.Query> + (sql, Tuple.Create, splitOn: "AddressId, Id").First(); + + personWithAddress.Item1.PersonId.IsEqualTo(1); + personWithAddress.Item1.Name.IsEqualTo("bob"); + personWithAddress.Item2.AddressId.IsEqualTo(2); + personWithAddress.Item2.Name.IsEqualTo("abc street"); + personWithAddress.Item2.PersonId.IsEqualTo(1); + personWithAddress.Item3.Id.IsEqualTo(3); + personWithAddress.Item3.Name.IsEqualTo("fred"); + } + + 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; } + } + class Extra + { + public int Id { get; set; } + public string Name { get; set; } + } + + [Fact] + public void TestMultiMappingWithNonReturnedProperty() + { + var sql = @"select + 1 as PostId, 'Title' as Title, + 2 as BlogId, 'Blog' as Title"; + var postWithBlog = connection.Query(sql, + (p, b) => + { + p.Blog = b; + return p; + }, splitOn: "BlogId").First(); + + postWithBlog.PostId.IsEqualTo(1); + postWithBlog.Title.IsEqualTo("Title"); + postWithBlog.Blog.BlogId.IsEqualTo(2); + postWithBlog.Blog.Title.IsEqualTo("Blog"); + } + + class Post_DupeProp + { + public int PostId { get; set; } + public string Title { get; set; } + public int BlogId { get; set; } + public Blog_DupeProp Blog { get; set; } + } + class Blog_DupeProp + { + public int BlogId { get; set; } + public string Title { get; set; } + } + } +} diff --git a/Dapper.DNX.Tests/Tests.Parameters.cs b/Dapper.DNX.Tests/Tests.Parameters.cs new file mode 100644 index 0000000000000000000000000000000000000000..a705e8bbd52c7c8b8913fe17497bd1cc3095c98a --- /dev/null +++ b/Dapper.DNX.Tests/Tests.Parameters.cs @@ -0,0 +1,990 @@ +using Dapper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Dynamic; +using System.Linq; +using Xunit; + +#if DOTNET5_2 +using IDbCommand = System.Data.Common.DbCommand; +using IDbDataParameter = System.Data.Common.DbParameter; +using IDbConnection = System.Data.Common.DbConnection; +using IDbTransaction = System.Data.Common.DbTransaction; +using IDataReader = System.Data.Common.DbDataReader; +#endif + +namespace SqlMapper +{ + public partial class Tests + { + public class DbParams : Dapper.SqlMapper.IDynamicParameters, IEnumerable + { + private readonly List parameters = new List(); + public IEnumerator GetEnumerator() { return parameters.GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + public void Add(IDbDataParameter value) + { + parameters.Add(value); + } + void Dapper.SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, + Dapper.SqlMapper.Identity identity) + { + foreach (IDbDataParameter parameter in parameters) + command.Parameters.Add(parameter); + + } + } + + class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters + { + IEnumerable numbers; + public IntDynamicParam(IEnumerable numbers) + { + this.numbers = numbers; + } + + public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity) + { + var sqlCommand = (SqlCommand)command; + sqlCommand.CommandType = CommandType.StoredProcedure; + + List number_list = new List(); + + // Create an SqlMetaData object that describes our table type. + Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) }; + + foreach (int n in numbers) + { + // Create a new record, using the metadata array above. + Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition); + rec.SetInt32(0, n); // Set the value. + number_list.Add(rec); // Add it to the list. + } + + // Add the table parameter. + var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured); + p.Direction = ParameterDirection.Input; + p.TypeName = "int_list_type"; + p.Value = number_list; + + } + } + + class IntCustomParam : Dapper.SqlMapper.ICustomQueryParameter + { + IEnumerable numbers; + public IntCustomParam(IEnumerable numbers) + { + this.numbers = numbers; + } + + public void AddParameter(IDbCommand command, string name) + { + var sqlCommand = (SqlCommand)command; + sqlCommand.CommandType = CommandType.StoredProcedure; + + List number_list = new List(); + + // Create an SqlMetaData object that describes our table type. + Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) }; + + foreach (int n in numbers) + { + // Create a new record, using the metadata array above. + Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition); + rec.SetInt32(0, n); // Set the value. + number_list.Add(rec); // Add it to the list. + } + + // Add the table parameter. + var p = sqlCommand.Parameters.Add(name, SqlDbType.Structured); + p.Direction = ParameterDirection.Input; + p.TypeName = "int_list_type"; + p.Value = number_list; + } + } + + +#if EXTERNALS + [Fact] + public void TestTVPWithAnonymousObject() + { + try + { + connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)"); + connection.Execute("CREATE PROC get_ints @integers int_list_type READONLY AS select * from @integers"); + + var nums = connection.Query("get_ints", new { integers = new IntCustomParam(new int[] { 1, 2, 3 }) }, commandType: CommandType.StoredProcedure).ToList(); + nums[0].IsEqualTo(1); + nums[1].IsEqualTo(2); + nums[2].IsEqualTo(3); + nums.Count.IsEqualTo(3); + + } + finally + { + try + { + connection.Execute("DROP PROC get_ints"); + } + finally + { + connection.Execute("DROP TYPE int_list_type"); + } + } + } + + // SQL Server specific test to demonstrate TVP + [Fact] + public void TestTVP() + { + try + { + connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)"); + connection.Execute("CREATE PROC get_ints @ints int_list_type READONLY AS select * from @ints"); + + var nums = connection.Query("get_ints", new IntDynamicParam(new int[] { 1, 2, 3 })).ToList(); + nums[0].IsEqualTo(1); + nums[1].IsEqualTo(2); + nums[2].IsEqualTo(3); + nums.Count.IsEqualTo(3); + + } + finally + { + try + { + connection.Execute("DROP PROC get_ints"); + } + finally + { + connection.Execute("DROP TYPE int_list_type"); + } + } + } + + class DynamicParameterWithIntTVP : Dapper.DynamicParameters, Dapper.SqlMapper.IDynamicParameters + { + IEnumerable numbers; + public DynamicParameterWithIntTVP(IEnumerable numbers) + { + this.numbers = numbers; + } + + public new void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity) + { + base.AddParameters(command, identity); + + var sqlCommand = (SqlCommand)command; + sqlCommand.CommandType = CommandType.StoredProcedure; + + List number_list = new List(); + + // Create an SqlMetaData object that describes our table type. + Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) }; + + foreach (int n in numbers) + { + // Create a new record, using the metadata array above. + Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition); + rec.SetInt32(0, n); // Set the value. + number_list.Add(rec); // Add it to the list. + } + + // Add the table parameter. + var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured); + p.Direction = ParameterDirection.Input; + p.TypeName = "int_list_type"; + p.Value = number_list; + + } + } + + [Fact] + public void TestTVPWithAdditionalParams() + { + try + { + connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)"); + connection.Execute("CREATE PROC get_values @ints int_list_type READONLY, @stringParam varchar(20), @dateParam datetime AS select i.*, @stringParam as stringParam, @dateParam as dateParam from @ints i"); + + var dynamicParameters = new DynamicParameterWithIntTVP(new int[] { 1, 2, 3 }); + dynamicParameters.AddDynamicParams(new { stringParam = "stringParam", dateParam = new DateTime(2012, 1, 1) }); + + var results = connection.Query("get_values", dynamicParameters, commandType: CommandType.StoredProcedure).ToList(); + results.Count.IsEqualTo(3); + for (int i = 0; i < results.Count; i++) + { + var result = results[i]; + Assert.IsEqualTo(i + 1, result.n); + Assert.IsEqualTo("stringParam", result.stringParam); + Assert.IsEqualTo(new DateTime(2012, 1, 1), result.dateParam); + } + + } + finally + { + try + { + connection.Execute("DROP PROC get_values"); + } + finally + { + connection.Execute("DROP TYPE int_list_type"); + } + } + } + + [Fact] + public void DataTableParameters() + { + try { connection.Execute("drop proc #DataTableParameters"); } + catch { } + try { connection.Execute("drop table #DataTableParameters"); } + catch { } + try { connection.Execute("drop type MyTVPType"); } + catch { } + connection.Execute("create type MyTVPType as table (id int)"); + connection.Execute("create proc #DataTableParameters @ids MyTVPType readonly as select count(1) from @ids"); + + var table = new DataTable { Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } }; + + int count = connection.Query("#DataTableParameters", new { ids = table.AsTableValuedParameter() }, commandType: CommandType.StoredProcedure).First(); + count.IsEqualTo(3); + + count = connection.Query("select count(1) from @ids", new { ids = table.AsTableValuedParameter("MyTVPType") }).First(); + count.IsEqualTo(3); + + try + { + connection.Query("select count(1) from @ids", new { ids = table.AsTableValuedParameter() }).First(); + throw new InvalidOperationException(); + } + catch (Exception ex) + { + ex.Message.Equals("The table type parameter 'ids' must have a valid type name."); + } + } + + [Fact] + public void SO29533765_DataTableParametersViaDynamicParameters() + { + try { connection.Execute("drop proc #DataTableParameters"); } catch { } + try { connection.Execute("drop table #DataTableParameters"); } catch { } + try { connection.Execute("drop type MyTVPType"); } catch { } + connection.Execute("create type MyTVPType as table (id int)"); + connection.Execute("create proc #DataTableParameters @ids MyTVPType readonly as select count(1) from @ids"); + + var table = new DataTable { TableName="MyTVPType", Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } }; + table.SetTypeName(table.TableName); // per SO29533765 + IDictionary args = new Dictionary(); + args.Add("ids", table); + int count = connection.Query("#DataTableParameters", args, commandType: CommandType.StoredProcedure).First(); + count.IsEqualTo(3); + + count = connection.Query("select count(1) from @ids", args).First(); + count.IsEqualTo(3); + } + + [Fact] + public void SO26468710_InWithTVPs() + { + // this is just to make it re-runnable; normally you only do this once + try { connection.Execute("drop type MyIdList"); } + catch { } + connection.Execute("create type MyIdList as table(id int);"); + + DataTable ids = new DataTable + { + Columns = { { "id", typeof(int) } }, + Rows = { { 1 }, { 3 }, { 5 } } + }; + ids.SetTypeName("MyIdList"); + int sum = connection.Query(@" + declare @tmp table(id int not null); + insert @tmp (id) values(1), (2), (3), (4), (5), (6), (7); + select * from @tmp t inner join @ids i on i.id = t.id", new { ids }).Sum(); + sum.IsEqualTo(9); + } + + [Fact] + public void DataTableParametersWithExtendedProperty() + { + try { connection.Execute("drop proc #DataTableParameters"); } + catch { } + try { connection.Execute("drop table #DataTableParameters"); } + catch { } + try { connection.Execute("drop type MyTVPType"); } + catch { } + connection.Execute("create type MyTVPType as table (id int)"); + connection.Execute("create proc #DataTableParameters @ids MyTVPType readonly as select count(1) from @ids"); + + var table = new DataTable { Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } }; + table.SetTypeName("MyTVPType"); // <== extended metadata + int count = connection.Query("#DataTableParameters", new { ids = table }, commandType: CommandType.StoredProcedure).First(); + count.IsEqualTo(3); + + count = connection.Query("select count(1) from @ids", new { ids = table }).First(); + count.IsEqualTo(3); + + try + { + connection.Query("select count(1) from @ids", new { ids = table }).First(); + throw new InvalidOperationException(); + } + catch (Exception ex) + { + ex.Message.Equals("The table type parameter 'ids' must have a valid type name."); + } + } + + [Fact] + public void SupportInit() + { + var obj = connection.Query("select 'abc' as Value").Single(); + obj.Value.Equals("abc"); + obj.Flags.Equals(31); + } + + class HazGeo + { + public int Id { get; set; } + public DbGeography Geo { get; set; } + public DbGeometry Geometry { get; set; } + } + class HazSqlGeo + { + public int Id { get; set; } + public SqlGeography Geo { get; set; } + public SqlGeometry Geometry { get; set; } + } + + [Fact] + public void DBGeography_SO24405645_SO24402424() + { + Dapper.EntityFramework.Handlers.Register(); + + connection.Execute("create table #Geo (id int, geo geography, geometry geometry)"); + + var obj = new HazGeo + { + Id = 1, + Geo = DbGeography.LineFromText("LINESTRING(-122.360 47.656, -122.343 47.656 )", 4326), + Geometry = DbGeometry.LineFromText("LINESTRING (100 100, 20 180, 180 180)", 0) + }; + connection.Execute("insert #Geo(id, geo, geometry) values (@Id, @Geo, @Geometry)", obj); + var row = connection.Query("select * from #Geo where id=1").SingleOrDefault(); + row.IsNotNull(); + row.Id.IsEqualTo(1); + row.Geo.IsNotNull(); + row.Geometry.IsNotNull(); + } + + [Fact] + public void SqlGeography_SO25538154() + { + Dapper.SqlMapper.ResetTypeHandlers(); + connection.Execute("create table #SqlGeo (id int, geo geography, geometry geometry)"); + + var obj = new HazSqlGeo + { + Id = 1, + Geo = SqlGeography.STLineFromText(new SqlChars(new SqlString("LINESTRING(-122.360 47.656, -122.343 47.656 )")), 4326), + Geometry = SqlGeometry.STLineFromText(new SqlChars(new SqlString("LINESTRING (100 100, 20 180, 180 180)")), 0) + }; + connection.Execute("insert #SqlGeo(id, geo, geometry) values (@Id, @Geo, @Geometry)", obj); + var row = connection.Query("select * from #SqlGeo where id=1").SingleOrDefault(); + row.IsNotNull(); + row.Id.IsEqualTo(1); + row.Geo.IsNotNull(); + row.Geometry.IsNotNull(); + } + + [Fact] + public void NullableSqlGeometry() + { + Dapper.SqlMapper.ResetTypeHandlers(); + connection.Execute("create table #SqlNullableGeo (id int, geometry geometry null)"); + + var obj = new HazSqlGeo + { + Id = 1, + Geometry = null + }; + connection.Execute("insert #SqlNullableGeo(id, geometry) values (@Id, @Geometry)", obj); + var row = connection.Query("select * from #SqlNullableGeo where id=1").SingleOrDefault(); + row.IsNotNull(); + row.Id.IsEqualTo(1); + row.Geometry.IsNull(); + } + + [Fact] + public void SqlHierarchyId_SO18888911() + { + Dapper.SqlMapper.ResetTypeHandlers(); + var row = connection.Query("select 3 as [Id], hierarchyid::Parse('/1/2/3/') as [Path]").Single(); + row.Id.Equals(3); + row.Path.IsNotNull(); + + var val = connection.Query("select @Path", row).Single(); + val.IsNotNull(); + } + + public class HazSqlHierarchy + { + public int Id { get; set; } + public SqlHierarchyId Path { get; set; } + } + + // see http://stackoverflow.com/q/18847510/23354 + [Fact] + public void TestOleDbParameters() + { + using (var conn = ConnectViaOledb()) + { + var row = conn.Query("select Id = ?, Age = ?", + new { foo = 12, bar = 23 } // these names DO NOT MATTER!!! + ).Single(); + int age = row.Age; + int id = row.Id; + age.IsEqualTo(23); + id.IsEqualTo(12); + } + } + + System.Data.OleDb.OleDbConnection ConnectViaOledb() + { + var conn = new System.Data.OleDb.OleDbConnection(Program.OleDbConnectionString); + conn.Open(); + return conn; + } +#endif + + [Fact] + public void TestAppendingAnonClasses() + { + DynamicParameters p = new DynamicParameters(); + p.AddDynamicParams(new { A = 1, B = 2 }); + p.AddDynamicParams(new { C = 3, D = 4 }); + + var result = connection.Query("select @A a,@B b,@C c,@D d", p).Single(); + + ((int)result.a).IsEqualTo(1); + ((int)result.b).IsEqualTo(2); + ((int)result.c).IsEqualTo(3); + ((int)result.d).IsEqualTo(4); + } + + [Fact] + public void TestAppendingADictionary() + { + var dictionary = new Dictionary + { + {"A", 1}, + {"B", "two"} + }; + + DynamicParameters p = new DynamicParameters(); + p.AddDynamicParams(dictionary); + + var result = connection.Query("select @A a, @B b", p).Single(); + + ((int)result.a).IsEqualTo(1); + ((string)result.b).IsEqualTo("two"); + } + + [Fact] + public void TestAppendingAnExpandoObject() + { + dynamic expando = new ExpandoObject(); + expando.A = 1; + expando.B = "two"; + + DynamicParameters p = new DynamicParameters(); + p.AddDynamicParams(expando); + + var result = connection.Query("select @A a, @B b", p).Single(); + + ((int)result.a).IsEqualTo(1); + ((string)result.b).IsEqualTo("two"); + } + + [Fact] + public void TestAppendingAList() + { + DynamicParameters p = new DynamicParameters(); + var list = new int[] { 1, 2, 3 }; + p.AddDynamicParams(new { list }); + + var result = connection.Query("select * from (select 1 A union all select 2 union all select 3) X where A in @list", p).ToList(); + + result[0].IsEqualTo(1); + result[1].IsEqualTo(2); + result[2].IsEqualTo(3); + } + + [Fact] + public void TestAppendingAListAsDictionary() + { + DynamicParameters p = new DynamicParameters(); + var list = new int[] { 1, 2, 3 }; + var args = new Dictionary { { "ids", list } }; + p.AddDynamicParams(args); + + var result = connection.Query("select * from (select 1 A union all select 2 union all select 3) X where A in @ids", p).ToList(); + + result[0].IsEqualTo(1); + result[1].IsEqualTo(2); + result[2].IsEqualTo(3); + } + + [Fact] + public void TestAppendingAListByName() + { + DynamicParameters p = new DynamicParameters(); + var list = new int[] { 1, 2, 3 }; + p.Add("ids", list); + + var result = connection.Query("select * from (select 1 A union all select 2 union all select 3) X where A in @ids", p).ToList(); + + result[0].IsEqualTo(1); + result[1].IsEqualTo(2); + result[2].IsEqualTo(3); + } + + [Fact] + public void ParameterizedInWithOptimizeHint() + { + const string sql = @" +select count(1) +from( + select 1 as x + union all select 2 + union all select 5) y +where y.x in @vals +option (optimize for (@vals unKnoWn))"; + int count = connection.Query(sql, new { vals = new[] { 1, 2, 3, 4 } }).Single(); + count.IsEqualTo(2); + + count = connection.Query(sql, new { vals = new[] { 1 } }).Single(); + count.IsEqualTo(1); + + count = connection.Query(sql, new { vals = new int[0] }).Single(); + count.IsEqualTo(0); + } + + [Fact] + public void TestProcedureWithTimeParameter() + { + var p = new DynamicParameters(); + p.Add("a", TimeSpan.FromHours(10), dbType: DbType.Time); + + connection.Execute(@"CREATE PROCEDURE #TestProcWithTimeParameter + @a TIME + AS + BEGIN + SELECT @a + END"); + connection.Query("#TestProcWithTimeParameter", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(new TimeSpan(10, 0, 0)); + } + + [Fact] + public void TestUniqueIdentifier() + { + var guid = Guid.NewGuid(); + var result = connection.Query("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); + result.IsEqualTo(guid); + } + + [Fact] + public void TestNullableUniqueIdentifierNonNull() + { + Guid? guid = Guid.NewGuid(); + var result = connection.Query("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); + result.IsEqualTo(guid); + } + + [Fact] + public void TestNullableUniqueIdentifierNull() + { + Guid? guid = null; + var result = connection.Query("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); + result.IsEqualTo(guid); + } + + [Fact] + public void TestSupportForDynamicParameters() + { + var p = new DynamicParameters(); + p.Add("name", "bob"); + p.Add("age", dbType: DbType.Int32, direction: ParameterDirection.Output); + + connection.Query("set @age = 11 select @name", p).First().IsEqualTo("bob"); + + p.Get("age").IsEqualTo(11); + } + + [Fact] + public void TestSupportForDynamicParametersOutputExpressions() + { + 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.Execute(@" +SET @Occupation = 'grillmaster' +SET @PersonId = @PersonId + 1 +SET @NumberOfLegs = @NumberOfLegs - 1 +SET @AddressName = 'bobs burgers' +SET @AddressPersonId = @PersonId", p); + + bob.Occupation.IsEqualTo("grillmaster"); + bob.PersonId.IsEqualTo(2); + bob.NumberOfLegs.IsEqualTo(1); + bob.Address.Name.IsEqualTo("bobs burgers"); + bob.Address.PersonId.IsEqualTo(2); + } + + [Fact] + 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); + } + } + + [Fact] + 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(@" +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); + } + } + + [Fact] + 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(@" +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); + } + } + + [Fact] + 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().Single(); + y = multi.Read().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); + } + } + + [Fact] + public void TestSupportForExpandoObjectParameters() + { + dynamic p = new ExpandoObject(); + p.name = "bob"; + object parameters = p; + string result = connection.Query("select @name", parameters).First(); + result.IsEqualTo("bob"); + } + + [Fact] + public void SO25069578_DynamicParams_Procs() + { + var parameters = new DynamicParameters(); + parameters.Add("foo", "bar"); + // parameters = new DynamicParameters(parameters); + try { connection.Execute("drop proc SO25069578"); } + catch { } + connection.Execute("create proc SO25069578 @foo nvarchar(max) as select @foo as [X]"); + var tran = connection.BeginTransaction(); // gist used transaction; behaves the same either way, though + var row = connection.Query("SO25069578", parameters, + commandType: CommandType.StoredProcedure, transaction: tran).Single(); + tran.Rollback(); + row.X.IsEqualTo("bar"); + } + + [Fact] + public void SO25297173_DynamicIn() + { + var query = @" +declare @table table(value int not null); +insert @table values(1); +insert @table values(2); +insert @table values(3); +insert @table values(4); +insert @table values(5); +insert @table values(6); +insert @table values(7); +SELECT value FROM @table WHERE value IN @myIds"; + var queryParams = new Dictionary { + { "myIds", new [] { 5, 6 } } + }; + + var dynamicParams = new DynamicParameters(queryParams); + List result = connection.Query(query, dynamicParams).ToList(); + result.Count.IsEqualTo(2); + result.Contains(5).IsTrue(); + result.Contains(6).IsTrue(); + } + + [Fact] + public void Test_AddDynamicParametersRepeatedShouldWork() + { + var args = new DynamicParameters(); + args.AddDynamicParams(new { Foo = 123 }); + args.AddDynamicParams(new { Foo = 123 }); + int i = connection.Query("select @Foo", args).Single(); + i.IsEqualTo(123); + } + + [Fact] + public void AllowIDictionaryParameters() + { + var parameters = new Dictionary + { + { "param1", 0 } + }; + + connection.Query("SELECT @param1", parameters); + } + + [Fact] + public void TestParameterWithIndexer() + { + connection.Execute(@"create proc #TestProcWithIndexer + @A int +as +begin + select @A +end"); + var item = connection.Query("#TestProcWithIndexer", new ParameterWithIndexer(), commandType: CommandType.StoredProcedure).Single(); + } + public class ParameterWithIndexer + { + public int A { get; set; } + public virtual string this[string columnName] + { + get { return null; } + set { } + } + } + + [Fact] + public void TestMultipleParametersWithIndexer() + { + var order = connection.Query("select 1 A,2 B").First(); + + order.A.IsEqualTo(1); + order.B.IsEqualTo(2); + } + public class MultipleParametersWithIndexer : MultipleParametersWithIndexerDeclaringType + { + public int A { get; set; } + } + public class MultipleParametersWithIndexerDeclaringType + { + public object this[object field] { get { return null; } set { } } + public object this[object field, int index] { get { return null; } set { } } + public int B { get; set; } + } + + [Fact] + public void Issue182_BindDynamicObjectParametersAndColumns() + { + connection.Execute("create table #Dyno ([Id] uniqueidentifier primary key, [Name] nvarchar(50) not null, [Foo] bigint not null);"); + + var guid = Guid.NewGuid(); + var orig = new Dyno { Name = "T Rex", Id = guid, Foo = 123L }; + var result = connection.Execute("insert into #Dyno ([Id], [Name], [Foo]) values (@Id, @Name, @Foo);", orig); + + var fromDb = connection.Query("select * from #Dyno where Id=@Id", orig).Single(); + ((Guid)fromDb.Id).IsEqualTo(guid); + fromDb.Name.IsEqualTo("T Rex"); + ((long)fromDb.Foo).IsEqualTo(123L); + } + public class Dyno + { + public dynamic Id { get; set; } + public string Name { get; set; } + + public object Foo { get; set; } + } + + [Fact] + public void Issue151_ExpandoObjectArgsQuery() + { + dynamic args = new ExpandoObject(); + args.Id = 123; + args.Name = "abc"; + + var row = connection.Query("select @Id as [Id], @Name as [Name]", (object)args).Single(); + ((int)row.Id).Equals(123); + ((string)row.Name).Equals("abc"); + } + + [Fact] + public void Issue151_ExpandoObjectArgsExec() + { + dynamic args = new ExpandoObject(); + args.Id = 123; + args.Name = "abc"; + connection.Execute("create table #issue151 (Id int not null, Name nvarchar(20) not null)"); + connection.Execute("insert #issue151 values(@Id, @Name)", (object)args).IsEqualTo(1); + var row = connection.Query("select Id, Name from #issue151").Single(); + ((int)row.Id).Equals(123); + ((string)row.Name).Equals("abc"); + } + + [Fact] + public void Issue192_InParameterWorksWithSimilarNames() + { + var rows = connection.Query(@" +declare @Issue192 table ( + Field INT NOT NULL PRIMARY KEY IDENTITY(1,1), + Field_1 INT NOT NULL); +insert @Issue192(Field_1) values (1), (2), (3); +SELECT * FROM @Issue192 WHERE Field IN @Field AND Field_1 IN @Field_1", + new { Field = new[] { 1, 2 }, Field_1 = new[] { 2, 3 } }).Single(); + ((int)rows.Field).IsEqualTo(2); + ((int)rows.Field_1).IsEqualTo(2); + } + + [Fact] + public void Issue192_InParameterWorksWithSimilarNamesWithUnicode() + { + var rows = connection.Query(@" +declare @Issue192 table ( + Field INT NOT NULL PRIMARY KEY IDENTITY(1,1), + Field_1 INT NOT NULL); +insert @Issue192(Field_1) values (1), (2), (3); +SELECT * FROM @Issue192 WHERE Field IN @µ AND Field_1 IN @µµ", + new { µ = new[] { 1, 2 }, µµ = new[] { 2, 3 } }).Single(); + ((int)rows.Field).IsEqualTo(2); + ((int)rows.Field_1).IsEqualTo(2); + } + + [Fact] + public void Issue220_InParameterCanBeSpecifiedInAnyCase() + { + // note this might fail if your database server is case-sensitive + connection.Query("select * from (select 1 as Id) as X where Id in @ids", new { Ids = new[] { 1 } }) + .IsSequenceEqualTo(new[] { 1 }); + } + + [Fact] + public void SO30156367_DynamicParamsWithoutExec() + { + var dbParams = new DynamicParameters(); + dbParams.Add("Field1", 1); + var value = dbParams.Get("Field1"); + value.IsEqualTo(1); + } + } +} diff --git a/Dapper.DNX.Tests/Tests.QueryMultiple.cs b/Dapper.DNX.Tests/Tests.QueryMultiple.cs new file mode 100644 index 0000000000000000000000000000000000000000..d08b33fe17a5ad37020a0231db11f09402f24640 --- /dev/null +++ b/Dapper.DNX.Tests/Tests.QueryMultiple.cs @@ -0,0 +1,148 @@ +using Dapper; +using System; +using System.Data; +using System.Linq; +using Xunit; + +#if DOTNET5_2 +using IDbCommand = System.Data.Common.DbCommand; +using IDbDataParameter = System.Data.Common.DbParameter; +using IDbConnection = System.Data.Common.DbConnection; +using IDbTransaction = System.Data.Common.DbTransaction; +using IDataReader = System.Data.Common.DbDataReader; +#endif + +namespace SqlMapper +{ + public partial class Tests + { + [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() + { + var 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.IsEqualTo(i, 1); + Assert.IsEqualTo(s, "abc"); + Assert.IsEqualTo(j, 3); + } + + [Fact] + public void TestReadDynamicWithGridReader() + { + var 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); + + var 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(); + + users.Count.IsEqualTo(2); + posts.Count.IsEqualTo(3); + + ((int)users.First().Id).IsEqualTo(2); + ((int)posts.First().Id).IsEqualTo(3); + } + 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"); + retVal.IsEqualTo(3); + } + } +} diff --git a/Dapper.DNX.Tests/Tests.cs b/Dapper.DNX.Tests/Tests.cs index 9a374f2278f8a0b8c2ebfba3e35b293b54991f2d..7d8bd1d6c03e18aa2fd629898194abf7e8631c6d 100644 --- a/Dapper.DNX.Tests/Tests.cs +++ b/Dapper.DNX.Tests/Tests.cs @@ -24,6 +24,7 @@ using System.Threading; using System.Data.SqlTypes; using System.Diagnostics; +using Xunit; #if EXTERNALS using FirebirdSql.Data.FirebirdClient; using System.Data.Entity.Spatial; @@ -64,233 +65,23 @@ public GenericUriParser(GenericUriParserOptions options) namespace SqlMapper { - - class Tests + public partial class Tests : IDisposable { - SqlConnection connection = Program.GetOpenConnection(); - - public class AbstractInheritance - { - public abstract class Order - { - internal int Internal { get; set; } - protected int Protected { get; set; } - public int Public { get; set; } - - public int ProtectedVal => Protected; - } - - public class ConcreteOrder : Order - { - public int Concrete { get; set; } - } - } - - class UserWithConstructor - { - public UserWithConstructor(int id, string name) - { - Ident = id; - FullName = name; - } - public int Ident { get; set; } - public string FullName { get; set; } - } - - class PostWithConstructor - { - public PostWithConstructor(int id, int ownerid, string content) - { - Ident = id; - FullContent = content; - } - - public int Ident { get; set; } - public UserWithConstructor Owner { get; set; } - public string FullContent { get; set; } - public Comment Comment { get; set; } - } - - public void TestMultiMapWithConstructor() - { - var 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')"; - connection.Execute(createSql); - try - { - string sql = @"select * from #Posts p - left join #Users u on u.Id = p.OwnerId - Order by p.Id"; - PostWithConstructor[] data = connection.Query(sql, (post, user) => { post.Owner = user; return post; }).ToArray(); - var p = data.First(); - - p.FullContent.IsEqualTo("Sams Post1"); - p.Ident.IsEqualTo(1); - p.Owner.FullName.IsEqualTo("Sam"); - p.Owner.Ident.IsEqualTo(99); - - data[2].Owner.IsNull(); - } - finally - { - connection.Execute("drop table #Users drop table #Posts"); - } - } - - - class MultipleConstructors - { - public MultipleConstructors() - { - - } - public MultipleConstructors(int a, string b) - { - A = a + 1; - B = b + "!"; - } - public int A { get; set; } - public string B { get; set; } - } - - public void TestMultipleConstructors() - { - MultipleConstructors mult = connection.Query("select 0 A, 'Dapper' b").First(); - mult.A.IsEqualTo(0); - mult.B.IsEqualTo("Dapper"); - } - - class ConstructorsWithAccessModifiers - { - private ConstructorsWithAccessModifiers() - { - } - public ConstructorsWithAccessModifiers(int a, string b) - { - A = a + 1; - B = b + "!"; - } - public int A { get; set; } - public string B { get; set; } - } - - public void TestConstructorsWithAccessModifiers() - { - ConstructorsWithAccessModifiers value = connection.Query("select 0 A, 'Dapper' b").First(); - value.A.IsEqualTo(1); - value.B.IsEqualTo("Dapper!"); - } - - class NoDefaultConstructor - { - public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1) - { - A = a1; - B = b1; - F = f1; - S = s1; - G = G1; - } - public int A { get; set; } - public int? B { get; set; } - public float F { get; set; } - public string S { get; set; } - public Guid G { get; set; } - } + readonly SqlConnection connection; - public void TestNoDefaultConstructor() + public Tests() { - var guid = Guid.NewGuid(); - NoDefaultConstructor nodef = connection.Query("select CAST(NULL AS integer) A1, CAST(NULL AS integer) b1, CAST(NULL AS real) f1, 'Dapper' s1, G1 = @id", new { id = guid }).First(); - nodef.A.IsEqualTo(0); - nodef.B.IsEqualTo(null); - nodef.F.IsEqualTo(0); - nodef.S.IsEqualTo("Dapper"); - nodef.G.IsEqualTo(guid); - } - - class NoDefaultConstructorWithChar - { - public NoDefaultConstructorWithChar(char c1, char? c2, char? c3) - { - Char1 = c1; - Char2 = c2; - Char3 = c3; - } - public char Char1 { get; set; } - public char? Char2 { get; set; } - public char? Char3 { get; set; } - } - - public void TestNoDefaultConstructorWithChar() - { - const char c1 = 'ą'; - const char c3 = 'ó'; - NoDefaultConstructorWithChar nodef = connection.Query("select @c1 c1, @c2 c2, @c3 c3", new { c1 = c1, c2 = (char?)null, c3 = c3 }).First(); - nodef.Char1.IsEqualTo(c1); - nodef.Char2.IsEqualTo(null); - nodef.Char3.IsEqualTo(c3); - } - - class NoDefaultConstructorWithEnum - { - public NoDefaultConstructorWithEnum(ShortEnum e1, ShortEnum? n1, ShortEnum? n2) - { - E = e1; - NE1 = n1; - NE2 = n2; - } - public ShortEnum E { get; set; } - public ShortEnum? NE1 { get; set; } - public ShortEnum? NE2 { get; set; } + connection = Program.GetOpenConnection(); } - public void TestNoDefaultConstructorWithEnum() - { - NoDefaultConstructorWithEnum nodef = connection.Query("select cast(2 as smallint) E1, cast(5 as smallint) n1, cast(null as smallint) n2").First(); - nodef.E.IsEqualTo(ShortEnum.Two); - nodef.NE1.IsEqualTo(ShortEnum.Five); - nodef.NE2.IsEqualTo(null); - } -#if EXTERNALS - class NoDefaultConstructorWithBinary - { - public System.Data.Linq.Binary Value { get; set; } - public int Ynt { get; set; } - public NoDefaultConstructorWithBinary(System.Data.Linq.Binary val) - { - Value = val; - } - } - public void TestNoDefaultConstructorBinary() + public void Dispose() { - byte[] orig = new byte[20]; - new Random(123456).NextBytes(orig); - var input = new System.Data.Linq.Binary(orig); - var output = connection.Query("select @input as val", new { input }).First().Value; - output.ToArray().IsSequenceEqualTo(orig); + connection?.Dispose(); } -#endif // http://stackoverflow.com/q/8593871 - public void TestAbstractInheritance() - { - var order = connection.Query("select 1 Internal,2 Protected,3 [Public],4 Concrete").First(); - - order.Internal.IsEqualTo(1); - order.ProtectedVal.IsEqualTo(2); - order.Public.IsEqualTo(3); - order.Concrete.IsEqualTo(4); - } + [Fact] public void TestListOfAnsiStrings() { var results = connection.Query("select * from (select 'a' str union select 'b' union select 'c') X where str in @strings", @@ -305,6 +96,7 @@ public void TestListOfAnsiStrings() results[1].IsEqualTo("b"); } + [Fact] public void TestNullableGuidSupport() { var guid = connection.Query("select null").First(); @@ -315,6 +107,7 @@ public void TestNullableGuidSupport() guid.IsEqualTo(guid2); } + [Fact] public void TestNonNullableGuidSupport() { var guid = Guid.NewGuid(); @@ -345,6 +138,7 @@ struct CarWithAllProps public Car.TrapEnum Trap { get; set; } } + [Fact] public void TestStructs() { var car = connection.Query("select 'Ford' Name, 21 Age, 2 Trap").First(); @@ -354,6 +148,7 @@ public void TestStructs() ((int)car.Trap).IsEqualTo(2); } + [Fact] public void TestStructAsParam() { var car1 = new CarWithAllProps { Name = "Ford", Age = 21, Trap = Car.TrapEnum.B }; @@ -365,27 +160,34 @@ public void TestStructAsParam() car2.Trap.IsEqualTo(car1.Trap); } + [Fact] public void SelectListInt() { connection.Query("select 1 union all select 2 union all select 3") .IsSequenceEqualTo(new[] { 1, 2, 3 }); } + + [Fact] public void SelectBinary() { connection.Query("select cast(1 as varbinary(4))").First().SequenceEqual(new byte[] { 1 }); } + + [Fact] public void PassInIntArray() { connection.Query("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[] { 1, 2, 3 }.AsEnumerable() }) .IsSequenceEqualTo(new[] { 1, 2, 3 }); } + [Fact] public void PassInEmptyIntArray() { connection.Query("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[0] }) .IsSequenceEqualTo(new int[0]); } + [Fact] public void TestSchemaChanged() { connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')"); @@ -405,6 +207,7 @@ public void TestSchemaChanged() } } + [Fact] public void TestSchemaChangedMultiMap() { connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')"); @@ -431,6 +234,7 @@ public void TestSchemaChangedMultiMap() } } + [Fact] public void TestReadMultipleIntegersWithSplitOnAny() { connection.Query>( @@ -438,12 +242,14 @@ public void TestReadMultipleIntegersWithSplitOnAny() .IsSequenceEqualTo(new[] { Tuple.Create(1, 2, 3), Tuple.Create(4, 5, 6) }); } + [Fact] public void TestDoubleParam() { connection.Query("select @d", new { d = 0.1d }).First() .IsEqualTo(0.1d); } + [Fact] public void TestBoolParam() { connection.Query("select @b", new { b = false }).First() @@ -452,12 +258,15 @@ public void TestBoolParam() // http://code.google.com/p/dapper-dot-net/issues/detail?id=70 // https://connect.microsoft.com/VisualStudio/feedback/details/381934/sqlparameter-dbtype-dbtype-time-sets-the-parameter-to-sqldbtype-datetime-instead-of-sqldbtype-time + + [Fact] public void TestTimeSpanParam() { connection.Query("select @ts", new { ts = TimeSpan.FromMinutes(42) }).First() .IsEqualTo(TimeSpan.FromMinutes(42)); } + [Fact] public void TestStrings() { connection.Query(@"select 'a' a union select 'b'") @@ -465,6 +274,7 @@ public void TestStrings() } // see http://stackoverflow.com/questions/16726709/string-format-with-sql-wildcard-causing-dapper-query-to-break + [Fact] public void CheckComplexConcat() { string end_wildcard = @" @@ -498,42 +308,6 @@ public void CheckComplexConcat() } - enum EnumParam : short - { - None, A, B - } - class EnumParamObject - { - public EnumParam A { get; set; } - public EnumParam? B { get; set; } - public EnumParam? C { get; set; } - } - class EnumParamObjectNonNullable - { - public EnumParam A { get; set; } - public EnumParam? B { get; set; } - public EnumParam? C { get; set; } - } - public void TestEnumParamsWithNullable() - { - EnumParam a = EnumParam.A; - EnumParam? b = EnumParam.B, c = null; - var obj = connection.Query("select @a as A, @b as B, @c as C", - new { a, b, c }).Single(); - obj.A.IsEqualTo(EnumParam.A); - obj.B.IsEqualTo(EnumParam.B); - obj.C.IsEqualTo(null); - } - public void TestEnumParamsWithoutNullable() - { - EnumParam a = EnumParam.A; - EnumParam b = EnumParam.B, c = 0; - var obj = connection.Query("select @a as A, @b as B, @c as C", - new { a, b, c }).Single(); - obj.A.IsEqualTo(EnumParam.A); - obj.B.IsEqualTo(EnumParam.B); - obj.C.IsEqualTo((EnumParam)0); - } public class Dog { public int? Age { get; set; } @@ -544,6 +318,7 @@ public class Dog public int IgnoredProperty { get { return 1; } } } + [Fact] public void TestExtraFields() { var guid = Guid.NewGuid(); @@ -558,29 +333,8 @@ public void TestExtraFields() dog.First().Id .IsEqualTo(guid); } -#if EXTERNALS - // see http://stackoverflow.com/q/18847510/23354 - public void TestOleDbParameters() - { - using (var conn = ConnectViaOledb()) - { - var row = conn.Query("select Id = ?, Age = ?", - new { foo = 12, bar = 23 } // these names DO NOT MATTER!!! - ).Single(); - int age = row.Age; - int id = row.Id; - age.IsEqualTo(23); - id.IsEqualTo(12); - } - } - System.Data.OleDb.OleDbConnection ConnectViaOledb() - { - var conn = new System.Data.OleDb.OleDbConnection(Program.OleDbConnectionString); - conn.Open(); - return conn; - } -#endif + [Fact] public void TestStrongType() { var guid = Guid.NewGuid(); @@ -596,11 +350,13 @@ public void TestStrongType() .IsEqualTo(guid); } + [Fact] public void TestSimpleNull() { connection.Query("select null").First().IsNull(); } + [Fact] public void TestExpando() { var rows = connection.Query("select 1 A, 2 B union all select 3, 4").ToList(); @@ -618,6 +374,7 @@ public void TestExpando() .IsEqualTo(4); } + [Fact] public void TestStringList() { connection.Query("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new { strings = new[] { "a", "b", "c" } }) @@ -627,6 +384,7 @@ public void TestStringList() .IsSequenceEqualTo(new string[0]); } + [Fact] public void TestExecuteCommand() { connection.Execute(@" @@ -638,6 +396,8 @@ public void TestExecuteCommand() set nocount on drop table #t", new { a = 1, b = 2 }).IsEqualTo(2); } + + [Fact] public void TestExecuteCommandWithHybridParameters() { var p = new DynamicParameters(new { a = 1, b = 2 }); @@ -645,6 +405,8 @@ public void TestExecuteCommandWithHybridParameters() connection.Execute(@"set @c = @a + @b", p); p.Get("@c").IsEqualTo(3); } + + [Fact] public void TestExecuteMultipleCommand() { connection.Execute("create table #t(i int)"); @@ -667,6 +429,7 @@ class Student public int Age { get; set; } } + [Fact] public void TestExecuteMultipleCommandStrongType() { connection.Execute("create table #t(Name nvarchar(max), Age int)"); @@ -687,6 +450,7 @@ public void TestExecuteMultipleCommandStrongType() } } + [Fact] public void TestExecuteMultipleCommandObjectArray() { connection.Execute("create table #t(i int)"); @@ -696,6 +460,7 @@ public void TestExecuteMultipleCommandObjectArray() sum.IsEqualTo(10); } + [Fact] public void TestMassiveStrings() { var str = new string('X', 20000); @@ -714,17 +479,19 @@ class TestObj private int PrivGet { get { return _priv; } } } + [Fact] public void TestSetInternal() { connection.Query("select 10 as [Internal]").First()._internal.IsEqualTo(10); } + [Fact] public void TestSetPrivate() { connection.Query("select 10 as [Priv]").First()._priv.IsEqualTo(10); } - + [Fact] public void TestExpandWithNullableFields() { var row = connection.Query("select null A, 2 B").Single(); @@ -736,6 +503,7 @@ public void TestExpandWithNullableFields() .IsEqualTo(2); } + [Fact] public void TestEnumeration() { var en = connection.Query("select 1 as one union all select 2 as one", buffered: false); @@ -761,6 +529,7 @@ public void TestEnumeration() gotException.IsTrue(); } + [Fact] public void TestEnumerationDynamic() { var en = connection.Query("select 1 as one union all select 2 as one", buffered: false); @@ -786,6 +555,7 @@ public void TestEnumerationDynamic() gotException.IsTrue(); } + [Fact] public void TestNakedBigInt() { long foo = 12345; @@ -793,6 +563,7 @@ public void TestNakedBigInt() foo.IsEqualTo(result); } + [Fact] public void TestBigIntMember() { long foo = 12345; @@ -802,357 +573,26 @@ public void TestBigIntMember() select * from @bar", new { foo }).Single(); result.Value.IsEqualTo(foo); } + class WithBigInt { public long Value { get; set; } } - class User - { - public int Id { get; set; } - public string Name { get; set; } - } - class Post - { - public int Id { get; set; } - public User Owner { get; set; } - public string Content { get; set; } - public Comment Comment { get; set; } - } - public void TestMultiMap() - { - var 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') -"; - connection.Execute(createSql); - try - { - var sql = - @"select * from #Posts p -left join #Users u on u.Id = p.OwnerId -Order by p.Id"; - - var data = connection.Query(sql, (post, user) => { post.Owner = user; return post; }).ToList(); - var p = data.First(); - - p.Content.IsEqualTo("Sams Post1"); - p.Id.IsEqualTo(1); - p.Owner.Name.IsEqualTo("Sam"); - p.Owner.Id.IsEqualTo(99); - - data[2].Owner.IsNull(); - } - finally - { - connection.Execute("drop table #Users drop table #Posts"); - } - } - - class ReviewBoard - { - public int Id { get; set; } - public string Name { get; set; } - public User User1 { get; set; } - public User User2 { get; set; } - public User User3 { get; set; } - public User User4 { get; set; } - public User User5 { get; set; } - public User User6 { get; set; } - public User User7 { get; set; } - public User User8 { get; set; } - public User User9 { get; set; } - } - - public void TestMultiMapArbitraryMaps() - { - // please excuse the trite example, but it is easier to follow than a more real-world one - var createSql = @" - create table #ReviewBoards (Id int, Name varchar(20), User1Id int, User2Id int, User3Id int, User4Id int, User5Id int, User6Id int, User7Id int, User8Id int, User9Id int) - create table #Users (Id int, Name varchar(20)) - - insert #Users values(1, 'User 1') - insert #Users values(2, 'User 2') - insert #Users values(3, 'User 3') - insert #Users values(4, 'User 4') - insert #Users values(5, 'User 5') - insert #Users values(6, 'User 6') - insert #Users values(7, 'User 7') - insert #Users values(8, 'User 8') - insert #Users values(9, 'User 9') - - insert #ReviewBoards values(1, 'Review Board 1', 1, 2, 3, 4, 5, 6, 7, 8, 9) -"; - connection.Execute(createSql); - try - { - var sql = @" - select - rb.Id, rb.Name, - u1.*, u2.*, u3.*, u4.*, u5.*, u6.*, u7.*, u8.*, u9.* - from #ReviewBoards rb - inner join #Users u1 on u1.Id = rb.User1Id - inner join #Users u2 on u2.Id = rb.User2Id - inner join #Users u3 on u3.Id = rb.User3Id - inner join #Users u4 on u4.Id = rb.User4Id - inner join #Users u5 on u5.Id = rb.User5Id - inner join #Users u6 on u6.Id = rb.User6Id - inner join #Users u7 on u7.Id = rb.User7Id - inner join #Users u8 on u8.Id = rb.User8Id - inner join #Users u9 on u9.Id = rb.User9Id -"; - - var types = new[] { typeof(ReviewBoard), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User), typeof(User) }; - - Func mapper = (objects) => - { - var board = (ReviewBoard)objects[0]; - board.User1 = (User)objects[1]; - board.User2 = (User)objects[2]; - board.User3 = (User)objects[3]; - board.User4 = (User)objects[4]; - board.User5 = (User)objects[5]; - board.User6 = (User)objects[6]; - board.User7 = (User)objects[7]; - board.User8 = (User)objects[8]; - board.User9 = (User)objects[9]; - return board; - }; - - var data = connection.Query(sql, types, mapper).ToList(); - - var p = data.First(); - p.Id.IsEqualTo(1); - p.Name.IsEqualTo("Review Board 1"); - p.User1.Id.IsEqualTo(1); - p.User2.Id.IsEqualTo(2); - p.User3.Id.IsEqualTo(3); - p.User4.Id.IsEqualTo(4); - p.User5.Id.IsEqualTo(5); - p.User6.Id.IsEqualTo(6); - p.User7.Id.IsEqualTo(7); - p.User8.Id.IsEqualTo(8); - p.User9.Id.IsEqualTo(9); - p.User1.Name.IsEqualTo("User 1"); - p.User2.Name.IsEqualTo("User 2"); - p.User3.Name.IsEqualTo("User 3"); - p.User4.Name.IsEqualTo("User 4"); - p.User5.Name.IsEqualTo("User 5"); - p.User6.Name.IsEqualTo("User 6"); - p.User7.Name.IsEqualTo("User 7"); - p.User8.Name.IsEqualTo("User 8"); - p.User9.Name.IsEqualTo("User 9"); - } - finally - { - connection.Execute("drop table #Users drop table #ReviewBoards"); - } - } - - public void TestMultiMapGridReader() - { - var 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') -"; - connection.Execute(createSql); - - var sql = -@"select p.*, u.Id, u.Name + '0' Name from #Posts p -left join #Users u on u.Id = p.OwnerId -Order by p.Id - -select p.*, u.Id, u.Name + '1' Name from #Posts p -left join #Users u on u.Id = p.OwnerId -Order by p.Id -"; - - var grid = connection.QueryMultiple(sql); - - for (int i = 0; i < 2; i++) - { - var data = grid.Read((post, user) => { post.Owner = user; return post; }).ToList(); - var p = data.First(); - - p.Content.IsEqualTo("Sams Post1"); - p.Id.IsEqualTo(1); - p.Owner.Name.IsEqualTo("Sam" + i); - p.Owner.Id.IsEqualTo(99); - - data[2].Owner.IsNull(); - } - - 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 = @" - 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') -"; - connection.Execute(createSql); - - var sql = -@"select * from #Posts p -left join #Users u on u.Id = p.OwnerId -Order by p.Id"; - - var data = connection.Query(sql, (post, user) => { post.Owner = user; return post; }).ToList(); - var p = data.First(); - - // hairy extension method support for dynamics - ((string)p.Content).IsEqualTo("Sams Post1"); - ((int)p.Id).IsEqualTo(1); - ((string)p.Owner.Name).IsEqualTo("Sam"); - ((int)p.Owner.Id).IsEqualTo(99); - - ((object)data[2].Owner).IsNull(); - - connection.Execute("drop table #Users drop table #Posts"); - } - - class Product - { - public int Id { get; set; } - public string Name { get; set; } - public Category Category { get; set; } - } - class Category - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - } - public void TestMultiMapWithSplit() // http://stackoverflow.com/q/6056778/23354 - { - var sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name"; - var product = connection.Query(sql, (prod, cat) => - { - prod.Category = cat; - return prod; - }).First(); - // assertions - product.Id.IsEqualTo(1); - product.Name.IsEqualTo("abc"); - product.Category.Id.IsEqualTo(2); - product.Category.Name.IsEqualTo("def"); - } - public void TestMultiMapWithSplitWithNullValue() // http://stackoverflow.com/q/10744728/449906 - { - var sql = @"select 1 as id, 'abc' as name, NULL as description, 'def' as name"; - var product = connection.Query(sql, (prod, cat) => - { - prod.Category = cat; - return prod; - }, splitOn: "description").First(); - // assertions - product.Id.IsEqualTo(1); - product.Name.IsEqualTo("abc"); - product.Category.IsNull(); - } - public void TestMultiMapWithSplitWithNullValueAndSpoofColumn() // http://stackoverflow.com/q/10744728/449906 - { - var sql = @"select 1 as id, 'abc' as name, 1 as spoof, NULL as description, 'def' as name"; - var product = connection.Query(sql, (prod, cat) => - { - prod.Category = cat; - return prod; - }, splitOn: "spoof").First(); - // assertions - product.Id.IsEqualTo(1); - product.Name.IsEqualTo("abc"); - product.Category.IsNotNull(); - product.Category.Id.IsEqualTo(0); - product.Category.Name.IsEqualTo("def"); - product.Category.Description.IsNull(); - } + [Fact] public void TestFieldsAndPrivates() { var data = connection.Query( @"select a=1,b=2,c=3,d=4,f='5'").Single(); - - data.a.IsEqualTo(1); data.GetB().IsEqualTo(2); data.c.IsEqualTo(3); data.GetD().IsEqualTo(4); data.e.IsEqualTo(5); - - } #if EXTERNALS + [Fact] public void ExecuteReader() { var dt = new DataTable(); @@ -1181,66 +621,6 @@ private string f } } - public void TestMultiReaderBasic() - { - var 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.IsEqualTo(i, 1); - Assert.IsEqualTo(s, "abc"); - Assert.IsEqualTo(j, 3); - } - public void TestMultiMappingVariations() - { - var sql = @"select 1 as Id, 'a' as Content, 2 as Id, 'b' as Content, 3 as Id, 'c' as Content, 4 as Id, 'd' as Content, 5 as Id, 'e' as Content"; - - var order = connection.Query(sql, (o, owner, creator) => { o.Owner = owner; o.Creator = creator; return o; }).First(); - - Assert.IsEqualTo(order.Id, 1); - Assert.IsEqualTo(order.Content, "a"); - Assert.IsEqualTo(order.Owner.Id, 2); - Assert.IsEqualTo(order.Owner.Content, "b"); - Assert.IsEqualTo(order.Creator.Id, 3); - Assert.IsEqualTo(order.Creator.Content, "c"); - - order = connection.Query(sql, (o, owner, creator, address) => - { - o.Owner = owner; - o.Creator = creator; - o.Owner.Address = address; - return o; - }).First(); - - Assert.IsEqualTo(order.Id, 1); - Assert.IsEqualTo(order.Content, "a"); - Assert.IsEqualTo(order.Owner.Id, 2); - Assert.IsEqualTo(order.Owner.Content, "b"); - Assert.IsEqualTo(order.Creator.Id, 3); - Assert.IsEqualTo(order.Creator.Content, "c"); - Assert.IsEqualTo(order.Owner.Address.Id, 4); - Assert.IsEqualTo(order.Owner.Address.Content, "d"); - - order = connection.Query(sql, (a, b, c, d, e) => { a.B = b; a.C = c; a.C.D = d; a.E = e; return a; }).First(); - - Assert.IsEqualTo(order.Id, 1); - Assert.IsEqualTo(order.Content, "a"); - Assert.IsEqualTo(order.B.Id, 2); - Assert.IsEqualTo(order.B.Content, "b"); - Assert.IsEqualTo(order.C.Id, 3); - Assert.IsEqualTo(order.C.Content, "c"); - Assert.IsEqualTo(order.C.D.Id, 4); - Assert.IsEqualTo(order.C.D.Content, "d"); - Assert.IsEqualTo(order.E.Id, 5); - Assert.IsEqualTo(order.E.Content, "e"); - - } - class InheritanceTest1 { public string Base1 { get; set; } @@ -1253,6 +633,7 @@ class InheritanceTest2 : InheritanceTest1 public string Derived2 { get; private set; } } + [Fact] public void TestInheritance() { // Test that inheritance works. @@ -1263,22 +644,8 @@ public void TestInheritance() list.First().Base2.IsEqualTo("Four"); } - - public class PostCE - { - public int ID { get; set; } - public string Title { get; set; } - public string Body { get; set; } - - public AuthorCE Author { get; set; } - } - - public class AuthorCE - { - public int ID { get; set; } - public string Name { get; set; } - } #if EXTERNALS + [Fact] public void MultiRSSqlCE() { if (File.Exists("Test.sdf")) @@ -1307,201 +674,24 @@ public void MultiRSSqlCE() cnn.Close(); } } -#endif - enum TestEnum : byte + + public class PostCE { - Bla = 1 + public int ID { get; set; } + public string Title { get; set; } + public string Body { get; set; } + + public AuthorCE Author { get; set; } } - class TestEnumClass + + public class AuthorCE { - public TestEnum? EnumEnum { get; set; } - } - class TestEnumClassNoNull - { - public TestEnum EnumEnum { get; set; } - } - public void TestEnumWeirdness() - { - connection.Query("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null); - connection.Query("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); - } - public void TestEnumStrings() - { - connection.Query("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); - connection.Query("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); - - connection.Query("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); - connection.Query("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); - } - - public void TestSupportForDynamicParameters() - { - var p = new DynamicParameters(); - p.Add("name", "bob"); - p.Add("age", dbType: DbType.Int32, direction: ParameterDirection.Output); - - connection.Query("set @age = 11 select @name", p).First().IsEqualTo("bob"); - - p.Get("age").IsEqualTo(11); - } - - public void TestSupportForDynamicParametersOutputExpressions() - { - 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.Execute(@" -SET @Occupation = 'grillmaster' -SET @PersonId = @PersonId + 1 -SET @NumberOfLegs = @NumberOfLegs - 1 -SET @AddressName = 'bobs burgers' -SET @AddressPersonId = @PersonId", p); - - 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.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(@" -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(@" -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().Single(); - y = multi.Read().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() - { - dynamic p = new ExpandoObject(); - p.name = "bob"; - object parameters = p; - string result = connection.Query("select @name", parameters).First(); - result.IsEqualTo("bob"); + public int ID { get; set; } + public string Name { get; set; } } +#endif + [Fact] public void TestProcSupport() { var p = new DynamicParameters(); @@ -1525,6 +715,7 @@ select 1111 } + [Fact] public void TestDbString() { var obj = connection.Query("select datalength(@a) as a, datalength(@b) as b, datalength(@c) as c, datalength(@d) as d, datalength(@e) as e, datalength(@f) as f", @@ -1545,6 +736,7 @@ public void TestDbString() ((int)obj.f).IsEqualTo(10); } + [Fact] public void TestDefaultDbStringDbType() { var origDefaultStringDbType = DbString.IsAnsiDefault; @@ -1562,101 +754,7 @@ public void TestDefaultDbStringDbType() } } - 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; } - } - - class Extra - { - public int Id { get; set; } - public string Name { get; set; } - } - - public void TestFlexibleMultiMapping() - { - var sql = -@"select - 1 as PersonId, 'bob' as Name, - 2 as AddressId, 'abc street' as Name, 1 as PersonId, - 3 as Id, 'fred' as Name - "; - var personWithAddress = connection.Query> - (sql, Tuple.Create, splitOn: "AddressId,Id").First(); - - personWithAddress.Item1.PersonId.IsEqualTo(1); - personWithAddress.Item1.Name.IsEqualTo("bob"); - personWithAddress.Item2.AddressId.IsEqualTo(2); - personWithAddress.Item2.Name.IsEqualTo("abc street"); - personWithAddress.Item2.PersonId.IsEqualTo(1); - personWithAddress.Item3.Id.IsEqualTo(3); - personWithAddress.Item3.Name.IsEqualTo("fred"); - - } - - public void TestMultiMappingWithSplitOnSpaceBetweenCommas() - { - var sql = @"select - 1 as PersonId, 'bob' as Name, - 2 as AddressId, 'abc street' as Name, 1 as PersonId, - 3 as Id, 'fred' as Name - "; - var personWithAddress = connection.Query> - (sql, Tuple.Create, splitOn: "AddressId, Id").First(); - - personWithAddress.Item1.PersonId.IsEqualTo(1); - personWithAddress.Item1.Name.IsEqualTo("bob"); - personWithAddress.Item2.AddressId.IsEqualTo(2); - personWithAddress.Item2.Name.IsEqualTo("abc street"); - personWithAddress.Item2.PersonId.IsEqualTo(1); - personWithAddress.Item3.Id.IsEqualTo(3); - personWithAddress.Item3.Name.IsEqualTo("fred"); - - } - - public void TestMultiMappingWithNonReturnedProperty() - { - var sql = @"select - 1 as PostId, 'Title' as Title, - 2 as BlogId, 'Blog' as Title"; - var postWithBlog = connection.Query(sql, - (p, b) => - { - p.Blog = b; - return p; - }, splitOn: "BlogId").First(); - - postWithBlog.PostId.IsEqualTo(1); - postWithBlog.Title.IsEqualTo("Title"); - postWithBlog.Blog.BlogId.IsEqualTo(2); - postWithBlog.Blog.Title.IsEqualTo("Blog"); - } - - class Post_DupeProp - { - public int PostId { get; set; } - public string Title { get; set; } - public int BlogId { get; set; } - public Blog_DupeProp Blog { get; set; } - } - - class Blog_DupeProp - { - public int BlogId { get; set; } - public string Title { get; set; } - } - + [Fact] public void TestFastExpandoSupportsIDictionary() { var row = connection.Query("select 1 A, 'two' B").First() as IDictionary; @@ -1664,6 +762,11 @@ public void TestFastExpandoSupportsIDictionary() row["B"].IsEqualTo("two"); } + [Fact] + public void TestDapperSetsPrivates() + { + connection.Query("select 'one' ShadowInDB").First().Shadow.IsEqualTo(1); + } class PrivateDan { @@ -1676,236 +779,6 @@ private string ShadowInDB } } } - public void TestDapperSetsPrivates() - { - connection.Query("select 'one' ShadowInDB").First().Shadow.IsEqualTo(1); - } - - - class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters - { - IEnumerable numbers; - public IntDynamicParam(IEnumerable numbers) - { - this.numbers = numbers; - } - - public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity) - { - var sqlCommand = (SqlCommand)command; - sqlCommand.CommandType = CommandType.StoredProcedure; - - List number_list = new List(); - - // Create an SqlMetaData object that describes our table type. - Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) }; - - foreach (int n in numbers) - { - // Create a new record, using the metadata array above. - Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition); - rec.SetInt32(0, n); // Set the value. - number_list.Add(rec); // Add it to the list. - } - - // Add the table parameter. - var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured); - p.Direction = ParameterDirection.Input; - p.TypeName = "int_list_type"; - p.Value = number_list; - - } - } -#if EXTERNALS - // SQL Server specific test to demonstrate TVP - public void TestTVP() - { - try - { - connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)"); - connection.Execute("CREATE PROC get_ints @ints int_list_type READONLY AS select * from @ints"); - - var nums = connection.Query("get_ints", new IntDynamicParam(new int[] { 1, 2, 3 })).ToList(); - nums[0].IsEqualTo(1); - nums[1].IsEqualTo(2); - nums[2].IsEqualTo(3); - nums.Count.IsEqualTo(3); - - } - finally - { - try - { - connection.Execute("DROP PROC get_ints"); - } - finally - { - connection.Execute("DROP TYPE int_list_type"); - } - } - } - - class DynamicParameterWithIntTVP : Dapper.DynamicParameters, Dapper.SqlMapper.IDynamicParameters - { - IEnumerable numbers; - public DynamicParameterWithIntTVP(IEnumerable numbers) - { - this.numbers = numbers; - } - - public new void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity) - { - base.AddParameters(command, identity); - - var sqlCommand = (SqlCommand)command; - sqlCommand.CommandType = CommandType.StoredProcedure; - - List number_list = new List(); - - // Create an SqlMetaData object that describes our table type. - Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) }; - - foreach (int n in numbers) - { - // Create a new record, using the metadata array above. - Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition); - rec.SetInt32(0, n); // Set the value. - number_list.Add(rec); // Add it to the list. - } - - // Add the table parameter. - var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured); - p.Direction = ParameterDirection.Input; - p.TypeName = "int_list_type"; - p.Value = number_list; - - } - } - - public void TestTVPWithAdditionalParams() - { - try - { - connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)"); - connection.Execute("CREATE PROC get_values @ints int_list_type READONLY, @stringParam varchar(20), @dateParam datetime AS select i.*, @stringParam as stringParam, @dateParam as dateParam from @ints i"); - - var dynamicParameters = new DynamicParameterWithIntTVP(new int[] { 1, 2, 3 }); - dynamicParameters.AddDynamicParams(new { stringParam = "stringParam", dateParam = new DateTime(2012, 1, 1) }); - - var results = connection.Query("get_values", dynamicParameters, commandType: CommandType.StoredProcedure).ToList(); - results.Count.IsEqualTo(3); - for (int i = 0; i < results.Count; i++) - { - var result = results[i]; - Assert.IsEqualTo(i + 1, result.n); - Assert.IsEqualTo("stringParam", result.stringParam); - Assert.IsEqualTo(new DateTime(2012, 1, 1), result.dateParam); - } - - } - finally - { - try - { - connection.Execute("DROP PROC get_values"); - } - finally - { - connection.Execute("DROP TYPE int_list_type"); - } - } - } -#endif - class IntCustomParam : Dapper.SqlMapper.ICustomQueryParameter - { - IEnumerable numbers; - public IntCustomParam(IEnumerable numbers) - { - this.numbers = numbers; - } - - public void AddParameter(IDbCommand command, string name) - { - var sqlCommand = (SqlCommand)command; - sqlCommand.CommandType = CommandType.StoredProcedure; - - List number_list = new List(); - - // Create an SqlMetaData object that describes our table type. - Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) }; - - foreach (int n in numbers) - { - // Create a new record, using the metadata array above. - Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition); - rec.SetInt32(0, n); // Set the value. - number_list.Add(rec); // Add it to the list. - } - - // Add the table parameter. - var p = sqlCommand.Parameters.Add(name, SqlDbType.Structured); - p.Direction = ParameterDirection.Input; - p.TypeName = "int_list_type"; - p.Value = number_list; - } - } -#if EXTERNALS - public void TestTVPWithAnonymousObject() - { - try - { - connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)"); - connection.Execute("CREATE PROC get_ints @integers int_list_type READONLY AS select * from @integers"); - - var nums = connection.Query("get_ints", new { integers = new IntCustomParam(new int[] { 1, 2, 3 }) }, commandType: CommandType.StoredProcedure).ToList(); - nums[0].IsEqualTo(1); - nums[1].IsEqualTo(2); - nums[2].IsEqualTo(3); - nums.Count.IsEqualTo(3); - - } - finally - { - try - { - connection.Execute("DROP PROC get_ints"); - } - finally - { - connection.Execute("DROP TYPE int_list_type"); - } - } - } -#endif - - class Parent - { - public int Id { get; set; } - public readonly List Children = new List(); - } - class Child - { - public int Id { get; set; } - } - public void ParentChildIdentityAssociations() - { - var lookup = new Dictionary(); - var parents = connection.Query(@"select 1 as [Id], 1 as [Id] union all select 1,2 union all select 2,3 union all select 1,4 union all select 3,5", - (parent, child) => - { - Parent found; - if (!lookup.TryGetValue(parent.Id, out found)) - { - lookup.Add(parent.Id, found = parent); - } - found.Children.Add(child); - return found; - }).Distinct().ToDictionary(p => p.Id); - parents.Count().IsEqualTo(3); - parents[1].Children.Select(c => c.Id).SequenceEqual(new[] { 1, 2, 4 }).IsTrue(); - parents[2].Children.Select(c => c.Id).SequenceEqual(new[] { 3 }).IsTrue(); - parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue(); - } /* TODO: @@ -1920,12 +793,7 @@ public void TestMagicParam() } * */ - class WithBizarreData - { - public GenericUriParser Foo { get; set; } - public int Bar { get; set; } - } - + [Fact] public void TestUnexpectedDataMessage() { string msg = null; @@ -1941,6 +809,7 @@ public void TestUnexpectedDataMessage() msg.IsEqualTo("The member Foo of type System.GenericUriParser cannot be used as a parameter value"); } + [Fact] public void TestUnexpectedButFilteredDataMessage() { int i = connection.Query("select @Bar", new WithBizarreData { Foo = new GenericUriParser(GenericUriParserOptions.Default), Bar = 23 }).Single(); @@ -1948,11 +817,19 @@ public void TestUnexpectedButFilteredDataMessage() i.IsEqualTo(23); } + class WithBizarreData + { + public GenericUriParser Foo { get; set; } + public int Bar { get; set; } + } + class WithCharValue { public char Value { get; set; } public char? ValueNullable { get; set; } } + + [Fact] public void TestCharInputAndOutput() { const char test = '〠'; @@ -1964,6 +841,8 @@ public void TestCharInputAndOutput() obj.Value.IsEqualTo(test); } + + [Fact] public void TestNullableCharInputAndOutputNonNull() { char? test = '〠'; @@ -1975,6 +854,8 @@ public void TestNullableCharInputAndOutputNonNull() obj.ValueNullable.IsEqualTo(test); } + + [Fact] public void TestNullableCharInputAndOutputNull() { char? test = null; @@ -1986,6 +867,8 @@ public void TestNullableCharInputAndOutputNull() obj.ValueNullable.IsEqualTo(test); } + + [Fact] public void TestInvalidSplitCausesNiceError() { try @@ -2007,74 +890,7 @@ public void TestInvalidSplitCausesNiceError() } } - - - class Comment - { - public int Id { get; set; } - public string CommentData { get; set; } - } - - - public void TestMultiMapThreeTypesWithGridReader() - { - var createSql = @" - create table #Users (Id int, Name varchar(20)) - create table #Posts (Id int, OwnerId int, Content varchar(20)) - create table #Comments (Id int, PostId int, CommentData 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') - - insert #Comments values(1, 1, 'Comment 1')"; - connection.Execute(createSql); - try - { - var sql = @"SELECT p.* FROM #Posts p - -select p.*, u.Id, u.Name + '0' Name, c.Id, c.CommentData from #Posts p -left join #Users u on u.Id = p.OwnerId -left join #Comments c on c.PostId = p.Id -where p.Id = 1 -Order by p.Id"; - - var grid = connection.QueryMultiple(sql); - - var post1 = grid.Read().ToList(); - - var post2 = grid.Read((post, user, comment) => { post.Owner = user; post.Comment = comment; return post; }).SingleOrDefault(); - - post2.Comment.Id.IsEqualTo(1); - post2.Owner.Id.IsEqualTo(99); - - } - finally - { - connection.Execute("drop table #Users drop table #Posts drop table #Comments"); - } - } - - public class DbParams : Dapper.SqlMapper.IDynamicParameters, IEnumerable - { - private readonly List parameters = new List(); - public IEnumerator GetEnumerator() { return parameters.GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } - public void Add(IDbDataParameter value) - { - parameters.Add(value); - } - void Dapper.SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, - Dapper.SqlMapper.Identity identity) - { - foreach (IDbDataParameter parameter in parameters) - command.Parameters.Add(parameter); - - } - } + [Fact] public void TestCustomParameters() { var args = new DbParams { @@ -2087,44 +903,8 @@ public void TestCustomParameters() foo.IsEqualTo(123); bar.IsEqualTo("abc"); } - - - public void TestReadDynamicWithGridReader() - { - var 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); - - var 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(); - - users.Count.IsEqualTo(2); - posts.Count.IsEqualTo(3); - - ((int)users.First().Id).IsEqualTo(2); - ((int)posts.First().Id).IsEqualTo(3); - } - finally - { - connection.Execute("drop table #Users drop table #Posts"); - } - } - + + [Fact] public void TestDynamicParamNullSupport() { var p = new DynamicParameters(); @@ -2134,31 +914,10 @@ public void TestDynamicParamNullSupport() p.Get("@b").IsNull(); } - class Foo1 - { -#pragma warning disable 0649 - public int Id; -#pragma warning restore 0649 - public int BarId { get; set; } - } - class Bar1 - { -#pragma warning disable 0649 - public int BarId; -#pragma warning restore 0649 - public string Name { get; set; } - } - public void TestMultiMapperIsNotConfusedWithUnorderedCols() - { - var result = connection.Query>("select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name", Tuple.Create, splitOn: "BarId").First(); - result.Item1.Id.IsEqualTo(1); - result.Item1.BarId.IsEqualTo(2); - result.Item2.BarId.IsEqualTo(3); - result.Item2.Name.IsEqualTo("a"); - } #if EXTERNALS + [Fact] public void TestLinqBinaryToClass() { byte[] orig = new byte[20]; @@ -2169,7 +928,8 @@ public void TestLinqBinaryToClass() output.ToArray().IsSequenceEqualTo(orig); } - + + [Fact] public void TestLinqBinaryRaw() { byte[] orig = new byte[20]; @@ -2192,125 +952,23 @@ class WithPrivateConstructor public int Foo { get; set; } private WithPrivateConstructor() { } } - - public void TestWithNonPublicConstructor() - { - var output = connection.Query("select 1 as Foo").First(); - output.Foo.IsEqualTo(1); - } - - public void TestAppendingAnonClasses() - { - DynamicParameters p = new DynamicParameters(); - p.AddDynamicParams(new { A = 1, B = 2 }); - p.AddDynamicParams(new { C = 3, D = 4 }); - - var result = connection.Query("select @A a,@B b,@C c,@D d", p).Single(); - - ((int)result.a).IsEqualTo(1); - ((int)result.b).IsEqualTo(2); - ((int)result.c).IsEqualTo(3); - ((int)result.d).IsEqualTo(4); - } - - public void TestAppendingADictionary() - { - var dictionary = new Dictionary(); - dictionary.Add("A", 1); - dictionary.Add("B", "two"); - - DynamicParameters p = new DynamicParameters(); - p.AddDynamicParams(dictionary); - - var result = connection.Query("select @A a, @B b", p).Single(); - - ((int)result.a).IsEqualTo(1); - ((string)result.b).IsEqualTo("two"); - } - - public void TestAppendingAnExpandoObject() - { - dynamic expando = new System.Dynamic.ExpandoObject(); - expando.A = 1; - expando.B = "two"; - - DynamicParameters p = new DynamicParameters(); - p.AddDynamicParams(expando); - - var result = connection.Query("select @A a, @B b", p).Single(); - - ((int)result.a).IsEqualTo(1); - ((string)result.b).IsEqualTo("two"); - } - - public void TestAppendingAList() - { - DynamicParameters p = new DynamicParameters(); - var list = new int[] { 1, 2, 3 }; - p.AddDynamicParams(new { list }); - - var result = connection.Query("select * from (select 1 A union all select 2 union all select 3) X where A in @list", p).ToList(); - - result[0].IsEqualTo(1); - result[1].IsEqualTo(2); - result[2].IsEqualTo(3); - } - - public void TestAppendingAListAsDictionary() - { - DynamicParameters p = new DynamicParameters(); - var list = new int[] { 1, 2, 3 }; - var args = new Dictionary(); - args.Add("ids", list); - p.AddDynamicParams(args); - - var result = connection.Query("select * from (select 1 A union all select 2 union all select 3) X where A in @ids", p).ToList(); - - result[0].IsEqualTo(1); - result[1].IsEqualTo(2); - result[2].IsEqualTo(3); - } - - public void TestAppendingAListByName() - { - DynamicParameters p = new DynamicParameters(); - var list = new int[] { 1, 2, 3 }; - p.Add("ids", list); - - var result = connection.Query("select * from (select 1 A union all select 2 union all select 3) X where A in @ids", p).ToList(); - - result[0].IsEqualTo(1); - result[1].IsEqualTo(2); - result[2].IsEqualTo(3); - } - - public void TestUniqueIdentifier() - { - var guid = Guid.NewGuid(); - var result = connection.Query("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); - result.IsEqualTo(guid); - } - public void TestNullableUniqueIdentifierNonNull() - { - Guid? guid = Guid.NewGuid(); - var result = connection.Query("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); - result.IsEqualTo(guid); - } - public void TestNullableUniqueIdentifierNull() + + [Fact] + public void TestWithNonPublicConstructor() { - Guid? guid = null; - var result = connection.Query("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single(); - result.IsEqualTo(guid); + var output = connection.Query("select 1 as Foo").First(); + output.Foo.IsEqualTo(1); } + [Fact] public void WorkDespiteHavingWrongStructColumnTypes() { var hazInt = connection.Query("select cast(1 as bigint) Value").Single(); hazInt.Value.Equals(1); } - + [Fact] public void TestProcWithOutParameter() { connection.Execute( @@ -2331,6 +989,8 @@ @Bar int connection.Execute("#TestProcWithOutParameter", args, commandType: CommandType.StoredProcedure); args.Get("ID").IsEqualTo(7); } + + [Fact] public void TestProcWithOutAndReturnParameter() { connection.Execute( @@ -2358,6 +1018,8 @@ struct CanHazInt { public int Value { get; set; } } + + [Fact] public void TestInt16Usage() { connection.Query("select cast(42 as smallint)").Single().IsEqualTo((short)42); @@ -2386,6 +1048,8 @@ public void TestInt16Usage() row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Six); row.NullableInt16Enum.IsEqualTo((ShortEnum?)null); } + + [Fact] public void TestInt32Usage() { connection.Query("select cast(42 as int)").Single().IsEqualTo((int)42); @@ -2438,6 +1102,7 @@ public enum IntEnum : int Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6 } + [Fact] public void TestTransactionCommit() { try @@ -2459,6 +1124,7 @@ public void TestTransactionCommit() } } + [Fact] public void TestTransactionRollback() { connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));"); @@ -2480,6 +1146,7 @@ public void TestTransactionRollback() } } + [Fact] public void TestCommandWithInheritedTransaction() { connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));"); @@ -2503,6 +1170,7 @@ public void TestCommandWithInheritedTransaction() } } + [Fact] public void TestReaderWhenResultsChange() { try @@ -2545,6 +1213,7 @@ class ResultsChangeType public int Z { get; set; } } + [Fact] public void TestCustomTypeMap() { // default mapping @@ -2595,6 +1264,7 @@ public class WrongTypes public bool D { get; set; } } + [Fact] public void TestWrongTypes_WithRightTypes() { var item = connection.Query("select 1 as A, cast(2.0 as float) as B, cast(3 as bigint) as C, cast(1 as bit) as D").Single(); @@ -2604,6 +1274,7 @@ public void TestWrongTypes_WithRightTypes() item.D.Equals(true); } + [Fact] public void TestWrongTypes_WithWrongTypes() { var item = connection.Query("select cast(1.0 as float) as A, 2 as B, 3 as C, cast(1 as bigint) as D").Single(); @@ -2613,57 +1284,8 @@ public void TestWrongTypes_WithWrongTypes() item.D.Equals(true); } - public void Test_AddDynamicParametersRepeatedShouldWork() - { - var args = new DynamicParameters(); - args.AddDynamicParams(new { Foo = 123 }); - args.AddDynamicParams(new { Foo = 123 }); - int i = connection.Query("select @Foo", args).Single(); - i.IsEqualTo(123); - } - - - public class ParameterWithIndexer - { - public int A { get; set; } - public virtual string this[string columnName] - { - get { return null; } - set { } - } - } - - public void TestParameterWithIndexer() - { - connection.Execute(@"create proc #TestProcWithIndexer - @A int -as -begin - select @A -end"); - var item = connection.Query("#TestProcWithIndexer", new ParameterWithIndexer(), commandType: CommandType.StoredProcedure).Single(); - } - - public class MultipleParametersWithIndexerDeclaringType - { - public object this[object field] { get { return null; } set { } } - public object this[object field, int index] { get { return null; } set { } } - public int B { get; set; } - } - - public class MultipleParametersWithIndexer : MultipleParametersWithIndexerDeclaringType - { - public int A { get; set; } - } - - public void TestMultipleParametersWithIndexer() - { - var order = connection.Query("select 1 A,2 B").First(); - - order.A.IsEqualTo(1); - order.B.IsEqualTo(2); - } + [Fact] public void Issue_40_AutomaticBoolConversion() { var user = connection.Query("select UserId=1,Email='abc',Password='changeme',Active=cast(1 as tinyint)").Single(); @@ -2677,7 +1299,7 @@ public class Issue40_User { public Issue40_User() { - Email = Password = String.Empty; + Email = Password = string.Empty; } public int UserID { get; set; } public string Email { get; set; } @@ -2691,6 +1313,8 @@ SqlConnection GetClosedConnection() if (conn.State != ConnectionState.Closed) throw new InvalidOperationException("should be closed!"); return conn; } + + [Fact] public void ExecuteFromClosed() { using (var conn = GetClosedConnection()) @@ -2707,6 +1331,8 @@ class Multi2 { public int Id { get; set; } } + + [Fact] public void QueryMultimapFromClosed() { using (var conn = GetClosedConnection()) @@ -2717,6 +1343,8 @@ public void QueryMultimapFromClosed() i.IsEqualTo(5); } } + + [Fact] public void QueryMultiple2FromClosed() { using (var conn = GetClosedConnection()) @@ -2731,6 +1359,8 @@ public void QueryMultiple2FromClosed() conn.State.IsEqualTo(ConnectionState.Closed); } } + + [Fact] public void ExecuteInvalidFromClosed() { using (var conn = GetClosedConnection()) @@ -2746,6 +1376,8 @@ public void ExecuteInvalidFromClosed() } } } + + [Fact] public void QueryFromClosed() { using (var conn = GetClosedConnection()) @@ -2755,6 +1387,8 @@ public void QueryFromClosed() i.IsEqualTo(1); } } + + [Fact] public void QueryInvalidFromClosed() { using (var conn = GetClosedConnection()) @@ -2770,6 +1404,8 @@ public void QueryInvalidFromClosed() } } } + + [Fact] public void QueryMultipleFromClosed() { using (var conn = GetClosedConnection()) @@ -2782,6 +1418,8 @@ public void QueryMultipleFromClosed() conn.State.IsEqualTo(ConnectionState.Closed); } } + + [Fact] public void QueryMultipleInvalidFromClosed() { using (var conn = GetClosedConnection()) @@ -2798,6 +1436,7 @@ public void QueryMultipleInvalidFromClosed() } } + [Fact] public void TestMultiSelectWithSomeEmptyGrids() { using (var reader = connection.QueryMultiple("select 1; select 2 where 1 = 0; select 3 where 1 = 0; select 4;")) @@ -2825,6 +1464,7 @@ public void TestMultiSelectWithSomeEmptyGrids() } } + [Fact] public void TestDynamicMutation() { var obj = connection.Query("select 1 as [a], 2 as [b], 3 as [c]").Single(); @@ -2853,6 +1493,8 @@ public void TestDynamicMutation() } } + + [Fact] public void TestIssue131() { var results = connection.Query( @@ -2868,7 +1510,9 @@ public void TestIssue131() asDict.ContainsKey("Surname").IsEqualTo(true); asDict.ContainsKey("AddressCount").IsEqualTo(false); } + // see http://stackoverflow.com/questions/16955357/issue-about-dapper + [Fact] public void TestSplitWithMissingMembers() { var result = connection.Query( @@ -2912,6 +1556,7 @@ public class Topic } // see http://stackoverflow.com/questions/13127886/dapper-returns-null-for-singleordefaultdatediff + [Fact] public void TestNullFromInt_NoRows() { var result = connection.Query( // case with rows @@ -2927,6 +1572,7 @@ public void TestNullFromInt_NoRows() } + [Fact] public void TestChangingDefaultStringTypeMappingToAnsiString() { var sql = "SELECT SQL_VARIANT_PROPERTY(CONVERT(sql_variant, @testParam),'BaseType') AS BaseType"; @@ -2944,6 +1590,7 @@ public void TestChangingDefaultStringTypeMappingToAnsiString() Dapper.SqlMapper.PurgeQueryCache(); Dapper.SqlMapper.AddTypeMap(typeof(string), DbType.String); // Restore Default to Unicode String } + #if DOTNET5_2 class TransactedConnection : IDbConnection { @@ -3053,6 +1700,8 @@ public void Open() } } #endif + + [Fact] public void TestDapperTableMetadataRetrieval() { // Test for a bug found in CS 51509960 where the following sequence would result in an InvalidOperationException being @@ -3071,6 +1720,7 @@ public void TestDapperTableMetadataRetrieval() ((string)first.value).IsEqualTo("test"); } + [Fact] public void TestIssue17648290() { var p = new DynamicParameters(); @@ -3102,6 +1752,7 @@ public void TestIssue17648290() p.Get("ErrorDescription").IsEqualTo("Completed successfully"); } + [Fact] public void TestDoubleDecimalConversions_SO18228523_RightWay() { var row = connection.Query( @@ -3111,6 +1762,8 @@ public void TestDoubleDecimalConversions_SO18228523_RightWay() row.C.Equals(3.0M); row.D.Equals(4.0M); } + + [Fact] public void TestDoubleDecimalConversions_SO18228523_WrongWay() { var row = connection.Query( @@ -3120,6 +1773,8 @@ public void TestDoubleDecimalConversions_SO18228523_WrongWay() row.C.Equals(3.0M); row.D.Equals(4.0M); } + + [Fact] public void TestDoubleDecimalConversions_SO18228523_Nulls() { var row = connection.Query( @@ -3129,6 +1784,7 @@ public void TestDoubleDecimalConversions_SO18228523_Nulls() row.C.Equals(0.0M); row.D.IsNull(); } + private static CultureInfo ActiveCulture { #if DOTNET5_2 @@ -3139,6 +1795,8 @@ private static CultureInfo ActiveCulture set { Thread.CurrentThread.CurrentCulture = value; } #endif } + + [Fact] public void TestParameterInclusionNotSensitiveToCurrentCulture() { // note this might fail if your database server is case-sensitive @@ -3154,6 +1812,8 @@ public void TestParameterInclusionNotSensitiveToCurrentCulture() ActiveCulture = current; } } + + [Fact] public void LiteralReplacement() { connection.Execute("create table #literal1 (id int not null, foo int not null)"); @@ -3165,6 +1825,8 @@ public void LiteralReplacement() int sum = connection.Query("select sum(id) + sum(foo) from #literal1").Single(); sum.IsEqualTo(123 + 456 + 1 + 2 + 3 + 4); } + + [Fact] public void LiteralReplacementDynamic() { var args = new DynamicParameters(); @@ -3192,6 +1854,7 @@ enum AnotherEnum : byte #if DOTNET5_2 [FrameworkFail("https://github.com/dotnet/corefx/issues/1613")] #endif + [Fact] public void AdoNetEnumValue() { using (var cmd = connection.CreateCommand()) @@ -3204,6 +1867,7 @@ public void AdoNetEnumValue() } } + [Fact] public void LiteralReplacementEnumAndString() { var args = new { x = AnEnum.B, y = 123.45M, z = AnotherEnum.A }; @@ -3216,6 +1880,7 @@ public void LiteralReplacementEnumAndString() z.Equals(AnotherEnum.A); } + [Fact] public void LiteralReplacementDynamicEnumAndString() { var args = new DynamicParameters(); @@ -3230,7 +1895,8 @@ public void LiteralReplacementDynamicEnumAndString() y.Equals(123.45M); z.Equals(AnotherEnum.A); } - + + [Fact] public void LiteralReplacementBoolean() { var row = connection.Query("select 42 where 1 = {=val}", new { val = true }).SingleOrDefault(); @@ -3239,6 +1905,8 @@ public void LiteralReplacementBoolean() row = connection.Query("select 42 where 1 = {=val}", new { val = false }).SingleOrDefault(); row.IsNull(); } + + [Fact] public void LiteralReplacementWithIn() { var data = connection.Query("select @x where 1 in @ids and 1 ={=a}", @@ -3250,6 +1918,7 @@ class MyRow public int x { get; set; } } + [Fact] public void LiteralIn() { connection.Execute("create table #literalin(id int not null);"); @@ -3263,43 +1932,7 @@ public void LiteralIn() count.IsEqualTo(2); } - public void ParameterizedInWithOptimizeHint() - { - const string sql = @" -select count(1) -from( - select 1 as x - union all select 2 - union all select 5) y -where y.x in @vals -option (optimize for (@vals unKnoWn))"; - int count = connection.Query(sql, new { vals = new[] { 1, 2, 3, 4 } }).Single(); - count.IsEqualTo(2); - - count = connection.Query(sql, new { vals = new[] { 1 } }).Single(); - count.IsEqualTo(1); - - count = connection.Query(sql, new { vals = new int[0] }).Single(); - count.IsEqualTo(0); - } - - - - - public void TestProcedureWithTimeParameter() - { - var p = new DynamicParameters(); - p.Add("a", TimeSpan.FromHours(10), dbType: DbType.Time); - - connection.Execute(@"CREATE PROCEDURE #TestProcWithTimeParameter - @a TIME - AS - BEGIN - SELECT @a - END"); - connection.Query("#TestProcWithTimeParameter", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(new TimeSpan(10, 0, 0)); - } - + [Fact] public void DbStringAnsi() { var a = connection.Query("select datalength(@x)", @@ -3314,7 +1947,9 @@ class HasInt32 { public int Value { get; set; } } + // http://stackoverflow.com/q/23696254/23354 + [Fact] public void DownwardIntegerConversion() { const string sql = "select cast(42 as bigint) as Value"; @@ -3332,111 +1967,8 @@ class HasDoubleDecimal public decimal C { get; set; } public decimal? D { get; set; } } -#if EXTERNALS - public void DataTableParameters() - { - try { connection.Execute("drop proc #DataTableParameters"); } - catch { } - try { connection.Execute("drop table #DataTableParameters"); } - catch { } - try { connection.Execute("drop type MyTVPType"); } - catch { } - connection.Execute("create type MyTVPType as table (id int)"); - connection.Execute("create proc #DataTableParameters @ids MyTVPType readonly as select count(1) from @ids"); - - var table = new DataTable { Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } }; - - int count = connection.Query("#DataTableParameters", new { ids = table.AsTableValuedParameter() }, commandType: CommandType.StoredProcedure).First(); - count.IsEqualTo(3); - - count = connection.Query("select count(1) from @ids", new { ids = table.AsTableValuedParameter("MyTVPType") }).First(); - count.IsEqualTo(3); - - try - { - connection.Query("select count(1) from @ids", new { ids = table.AsTableValuedParameter() }).First(); - throw new InvalidOperationException(); - } - catch (Exception ex) - { - ex.Message.Equals("The table type parameter 'ids' must have a valid type name."); - } - } - - public void SO29533765_DataTableParametersViaDynamicParameters() - { - try { connection.Execute("drop proc #DataTableParameters"); } catch { } - try { connection.Execute("drop table #DataTableParameters"); } catch { } - try { connection.Execute("drop type MyTVPType"); } catch { } - connection.Execute("create type MyTVPType as table (id int)"); - connection.Execute("create proc #DataTableParameters @ids MyTVPType readonly as select count(1) from @ids"); - - var table = new DataTable { TableName="MyTVPType", Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } }; - table.SetTypeName(table.TableName); // per SO29533765 - IDictionary args = new Dictionary(); - args.Add("ids", table); - int count = connection.Query("#DataTableParameters", args, commandType: CommandType.StoredProcedure).First(); - count.IsEqualTo(3); - - count = connection.Query("select count(1) from @ids", args).First(); - count.IsEqualTo(3); - } - public void SO26468710_InWithTVPs() - { - // this is just to make it re-runnable; normally you only do this once - try { connection.Execute("drop type MyIdList"); } - catch { } - connection.Execute("create type MyIdList as table(id int);"); - - DataTable ids = new DataTable - { - Columns = { { "id", typeof(int) } }, - Rows = { { 1 }, { 3 }, { 5 } } - }; - ids.SetTypeName("MyIdList"); - int sum = connection.Query(@" - declare @tmp table(id int not null); - insert @tmp (id) values(1), (2), (3), (4), (5), (6), (7); - select * from @tmp t inner join @ids i on i.id = t.id", new { ids }).Sum(); - sum.IsEqualTo(9); - } - public void DataTableParametersWithExtendedProperty() - { - try { connection.Execute("drop proc #DataTableParameters"); } - catch { } - try { connection.Execute("drop table #DataTableParameters"); } - catch { } - try { connection.Execute("drop type MyTVPType"); } - catch { } - connection.Execute("create type MyTVPType as table (id int)"); - connection.Execute("create proc #DataTableParameters @ids MyTVPType readonly as select count(1) from @ids"); - - var table = new DataTable { Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } }; - table.SetTypeName("MyTVPType"); // <== extended metadata - int count = connection.Query("#DataTableParameters", new { ids = table }, commandType: CommandType.StoredProcedure).First(); - count.IsEqualTo(3); - - count = connection.Query("select count(1) from @ids", new { ids = table }).First(); - count.IsEqualTo(3); - - try - { - connection.Query("select count(1) from @ids", new { ids = table }).First(); - throw new InvalidOperationException(); - } - catch (Exception ex) - { - ex.Message.Equals("The table type parameter 'ids' must have a valid type name."); - } - } - - public void SupportInit() - { - var obj = connection.Query("select 'abc' as Value").Single(); - obj.Value.Equals("abc"); - obj.Flags.Equals(31); - } -#endif + + [Fact] public void GuidIn_SO_24177902() { // invent and populate @@ -3463,92 +1995,8 @@ public void GuidIn_SO_24177902() rows[1].i.Equals(3); rows[1].g.Equals(c); } -#if EXTERNALS - class HazGeo - { - public int Id { get; set; } - public DbGeography Geo { get; set; } - public DbGeometry Geometry { get; set; } - } - class HazSqlGeo - { - public int Id { get; set; } - public SqlGeography Geo { get; set; } - public SqlGeometry Geometry { get; set; } - } - public void DBGeography_SO24405645_SO24402424() - { - Dapper.EntityFramework.Handlers.Register(); - - connection.Execute("create table #Geo (id int, geo geography, geometry geometry)"); - - var obj = new HazGeo - { - Id = 1, - Geo = DbGeography.LineFromText("LINESTRING(-122.360 47.656, -122.343 47.656 )", 4326), - Geometry = DbGeometry.LineFromText("LINESTRING (100 100, 20 180, 180 180)", 0) - }; - connection.Execute("insert #Geo(id, geo, geometry) values (@Id, @Geo, @Geometry)", obj); - var row = connection.Query("select * from #Geo where id=1").SingleOrDefault(); - row.IsNotNull(); - row.Id.IsEqualTo(1); - row.Geo.IsNotNull(); - row.Geometry.IsNotNull(); - } - - public void SqlGeography_SO25538154() - { - Dapper.SqlMapper.ResetTypeHandlers(); - connection.Execute("create table #SqlGeo (id int, geo geography, geometry geometry)"); - - var obj = new HazSqlGeo - { - Id = 1, - Geo = SqlGeography.STLineFromText(new SqlChars(new SqlString("LINESTRING(-122.360 47.656, -122.343 47.656 )")), 4326), - Geometry = SqlGeometry.STLineFromText(new SqlChars(new SqlString("LINESTRING (100 100, 20 180, 180 180)")), 0) - }; - connection.Execute("insert #SqlGeo(id, geo, geometry) values (@Id, @Geo, @Geometry)", obj); - var row = connection.Query("select * from #SqlGeo where id=1").SingleOrDefault(); - row.IsNotNull(); - row.Id.IsEqualTo(1); - row.Geo.IsNotNull(); - row.Geometry.IsNotNull(); - } - - public void NullableSqlGeometry() - { - Dapper.SqlMapper.ResetTypeHandlers(); - connection.Execute("create table #SqlNullableGeo (id int, geometry geometry null)"); - - var obj = new HazSqlGeo - { - Id = 1, - Geometry = null - }; - connection.Execute("insert #SqlNullableGeo(id, geometry) values (@Id, @Geometry)", obj); - var row = connection.Query("select * from #SqlNullableGeo where id=1").SingleOrDefault(); - row.IsNotNull(); - row.Id.IsEqualTo(1); - row.Geometry.IsNull(); - } - - public void SqlHierarchyId_SO18888911() - { - Dapper.SqlMapper.ResetTypeHandlers(); - var row = connection.Query("select 3 as [Id], hierarchyid::Parse('/1/2/3/') as [Path]").Single(); - row.Id.Equals(3); - row.Path.IsNotNull(); - - var val = connection.Query("select @Path", row).Single(); - val.IsNotNull(); - } - public class HazSqlHierarchy - { - public int Id { get; set; } - public SqlHierarchyId Path { get; set; } - } -#endif + [Fact] public void TypeBasedViaDynamic() { Type type = GetSomeType(); @@ -3561,6 +2009,8 @@ public void TypeBasedViaDynamic() a.IsEqualTo(123); b.IsEqualTo("abc"); } + + [Fact] public void TypeBasedViaType() { Type type = GetSomeType(); @@ -3572,6 +2022,8 @@ public void TypeBasedViaType() a.IsEqualTo(123); b.IsEqualTo("abc"); } + + [Fact] public void TypeBasedViaTypeMulti() { Type type = GetSomeType(); @@ -3595,7 +2047,8 @@ public void TypeBasedViaTypeMulti() a.IsEqualTo(456); b.IsEqualTo("def"); } - T CheetViaDynamic(T template, string query, object args) + + private T CheetViaDynamic(T template, string query, object args) { return connection.Query(query, args).SingleOrDefault(); } @@ -3625,6 +2078,8 @@ void ISupportInitialize.EndInit() } } #endif + + [Fact] public void SO24607639_NullableBools() { var obj = connection.Query( @@ -3643,6 +2098,7 @@ class HazBools public bool? C { get; set; } } + [Fact] public void SO24605346_ProcsAndStrings() { connection.Execute(@"create proc #GetPracticeRebateOrderByInvoiceNumber @TaxInvoiceNumber nvarchar(20) as @@ -3695,6 +2151,7 @@ public class MyResult public RatingValue CategoryRating { get; set; } } + [Fact] public void SO24740733_TestCustomValueHandler() { Dapper.SqlMapper.AddTypeHandler(RatingValueHandler.Default); @@ -3716,6 +2173,7 @@ public SO27024806Class(SO27024806Enum myField) public SO27024806Enum MyField { get; set; } } + [Fact] public void SO27024806_TestVarcharEnumMemberWithExplicitConstructor() { var foo = connection.Query("SELECT 'Foo' AS myField").Single(); @@ -3723,6 +2181,7 @@ public void SO27024806_TestVarcharEnumMemberWithExplicitConstructor() } + [Fact] public void SO24740733_TestCustomValueSingleColumn() { Dapper.SqlMapper.AddTypeHandler(RatingValueHandler.Default); @@ -3750,6 +2209,8 @@ public class MyObjectWithStringList { public List Names { get; set; } } + + [Fact] public void Issue253_TestIEnumerableTypeHandlerParsing() { Dapper.SqlMapper.ResetTypeHandlers(); @@ -3757,6 +2218,8 @@ public void Issue253_TestIEnumerableTypeHandlerParsing() var foo = connection.Query("SELECT 'Sam,Kyro' AS Names").Single(); foo.Names.IsSequenceEqualTo(new[] { "Sam", "Kyro" }); } + + [Fact] public void Issue253_TestIEnumerableTypeHandlerSetParameterValue() { Dapper.SqlMapper.ResetTypeHandlers(); @@ -3776,6 +2239,7 @@ public void Issue253_TestIEnumerableTypeHandlerSetParameterValue() } } + [Fact] public void Issue130_IConvertible() { dynamic row = connection.Query("select 1 as [a], '2' as [b]").Single(); @@ -3791,6 +2255,7 @@ public void Issue130_IConvertible() b.IsEqualTo("4"); } + [Fact] public void Issue22_ExecuteScalar() { int i = connection.ExecuteScalar("select 123"); @@ -3816,6 +2281,7 @@ public void Issue22_ExecuteScalar() #endif } + [Fact] public void Issue142_FailsNamedStatus() { var row1 = connection.Query("select @Status as [Status]", new { Status = StatusType.Started }).Single(); @@ -3843,8 +2309,7 @@ public enum Status : byte NotStarted = 1, Started = 2, Finished = 3 } - - + [Fact] public void Issue136_ValueTypeHandlers() { Dapper.SqlMapper.ResetTypeHandlers(); @@ -3862,6 +2327,7 @@ public void Issue136_ValueTypeHandlers() Dapper.SqlMapper.AddTypeHandler(typeof(LocalDate?), LocalDateHandler.Default); result = connection.Query("SELECT @NotNullable AS NotNullable, @NullableNotNull AS NullableNotNull, @NullableIsNull AS NullableIsNull", param).Single(); } + public class LocalDateHandler : Dapper.SqlMapper.TypeHandler { private LocalDateHandler() { } @@ -3955,6 +2421,7 @@ public enum E_ULong : ulong { A = 0, B = 1 } public decimal? N_N_Decimal { get; set; } } + [Fact] public void TestBigIntForEverythingWorks_SqlLite() { TestBigIntForEverythingWorks_SqlLite_ByDataType("bigint"); @@ -3965,6 +2432,7 @@ public void TestBigIntForEverythingWorks_SqlLite() TestBigIntForEverythingWorks_SqlLite_ByDataType("float(24)"); TestBigIntForEverythingWorks_SqlLite_ByDataType("float(53)"); } + private void TestBigIntForEverythingWorks_SqlLite_ByDataType(string dbType) { using (var reader = connection.ExecuteReader("select cast(1 as " + dbType + ")")) @@ -4077,45 +2545,33 @@ private void TestBigIntForEverythingWorks(T expected, string dbType) scalar.IsEqualTo(expected); } + [Fact] public void TestSubsequentQueriesSuccess() { var data0 = connection.Query("select 1 as [Id] where 1 = 0").ToList(); - data0.Count().IsEqualTo(0); + data0.Count.IsEqualTo(0); var data1 = connection.Query(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered)).ToList(); - data1.Count().IsEqualTo(0); + data1.Count.IsEqualTo(0); var data2 = connection.Query(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None)).ToList(); - data2.Count().IsEqualTo(0); + data2.Count.IsEqualTo(0); data0 = connection.Query("select 1 as [Id] where 1 = 0").ToList(); - data0.Count().IsEqualTo(0); + data0.Count.IsEqualTo(0); data1 = connection.Query(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered)).ToList(); - data1.Count().IsEqualTo(0); + data1.Count.IsEqualTo(0); data2 = connection.Query(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None)).ToList(); - data2.Count().IsEqualTo(0); + data2.Count.IsEqualTo(0); } class Fooz0 { public int Id { get; set; } } class Fooz1 { public int Id { get; set; } } class Fooz2 { public int Id { get; set; } } - public void SO25069578_DynamicParams_Procs() - { - var parameters = new DynamicParameters(); - parameters.Add("foo", "bar"); - // parameters = new DynamicParameters(parameters); - try { connection.Execute("drop proc SO25069578"); } - catch { } - connection.Execute("create proc SO25069578 @foo nvarchar(max) as select @foo as [X]"); - var tran = connection.BeginTransaction(); // gist used transaction; behaves the same either way, though - var row = connection.Query("SO25069578", parameters, - commandType: CommandType.StoredProcedure, transaction: tran).Single(); - tran.Rollback(); - row.X.IsEqualTo("bar"); - } + [Fact] public void Issue149_TypeMismatch_SequentialAccess() { string error; @@ -4138,41 +2594,7 @@ public class HazX public string X { get; set; } } - - public void SO25297173_DynamicIn() - { - var query = @" -declare @table table(value int not null); -insert @table values(1); -insert @table values(2); -insert @table values(3); -insert @table values(4); -insert @table values(5); -insert @table values(6); -insert @table values(7); -SELECT value FROM @table WHERE value IN @myIds"; - var queryParams = new Dictionary { - { "myIds", new [] { 5, 6 } } - }; - - var dynamicParams = new DynamicParameters(queryParams); - List result = connection.Query(query, dynamicParams).ToList(); - result.Count.IsEqualTo(2); - result.Contains(5).IsTrue(); - result.Contains(6).IsTrue(); - } - - public void AllowIDictionaryParameters() - { - var parameters = new Dictionary - { - { "param1", 0 } - }; - - connection.Query("SELECT @param1", parameters); - } - - + [Fact] public void Issue178_SqlServer() { const string sql = @"select count(*) from Issue178"; @@ -4236,7 +2658,8 @@ public void Issue178_SqlServer() count.IsEqualTo(1); } } - + + [Fact] public void PseudoPositionalParameters_Simple() { using (var connection = ConnectViaOledb()) @@ -4245,7 +2668,8 @@ public void PseudoPositionalParameters_Simple() value.IsEqualTo(9); } } - + + [Fact] public void PseudoPositionalParameters_Dynamic() { using (var connection = ConnectViaOledb()) @@ -4259,7 +2683,8 @@ public void PseudoPositionalParameters_Dynamic() value.IsEqualTo(9); } } - + + [Fact] public void PseudoPositionalParameters_ReusedParameter() { using (var connection = ConnectViaOledb()) @@ -4275,7 +2700,8 @@ public void PseudoPositionalParameters_ReusedParameter() } } } - + + [Fact] public void PseudoPositionalParameters_ExecSingle() { using (var connection = ConnectViaOledb()) @@ -4288,6 +2714,8 @@ public void PseudoPositionalParameters_ExecSingle() sum.IsEqualTo(6); } } + + [Fact] public void PseudoPositionalParameters_ExecMulti() { using (var connection = ConnectViaOledb()) @@ -4306,133 +2734,22 @@ public void PseudoPositionalParameters_ExecMulti() } } #endif + + [Fact] public void QueryBasicWithoutQuery() { int? i = connection.Query("print 'not a query'").FirstOrDefault(); i.IsNull(); } + [Fact] public void QueryComplexWithoutQuery() { var obj = connection.Query("print 'not a query'").FirstOrDefault(); obj.IsNull(); } - - public void Issue182_BindDynamicObjectParametersAndColumns() - { - connection.Execute("create table #Dyno ([Id] uniqueidentifier primary key, [Name] nvarchar(50) not null, [Foo] bigint not null);"); - - var guid = Guid.NewGuid(); - var orig = new Dyno { Name = "T Rex", Id = guid, Foo = 123L }; - var result = connection.Execute("insert into #Dyno ([Id], [Name], [Foo]) values (@Id, @Name, @Foo);", orig); - - var fromDb = connection.Query("select * from #Dyno where Id=@Id", orig).Single(); - ((Guid)fromDb.Id).IsEqualTo(guid); - fromDb.Name.IsEqualTo("T Rex"); - ((long)fromDb.Foo).IsEqualTo(123L); - } - public class Dyno - { - public dynamic Id { get; set; } - public string Name { get; set; } - - public object Foo { get; set; } - } - - public void Issue151_ExpandoObjectArgsQuery() - { - dynamic args = new ExpandoObject(); - args.Id = 123; - args.Name = "abc"; - - var row = connection.Query("select @Id as [Id], @Name as [Name]", (object)args).Single(); - ((int)row.Id).Equals(123); - ((string)row.Name).Equals("abc"); - } - - public void Issue151_ExpandoObjectArgsExec() - { - dynamic args = new ExpandoObject(); - args.Id = 123; - args.Name = "abc"; - connection.Execute("create table #issue151 (Id int not null, Name nvarchar(20) not null)"); - connection.Execute("insert #issue151 values(@Id, @Name)", (object)args).IsEqualTo(1); - var row = connection.Query("select Id, Name from #issue151").Single(); - ((int)row.Id).Equals(123); - ((string)row.Name).Equals("abc"); - } - - public void Issue192_InParameterWorksWithSimilarNames() - { - var rows = connection.Query(@" -declare @Issue192 table ( - Field INT NOT NULL PRIMARY KEY IDENTITY(1,1), - Field_1 INT NOT NULL); -insert @Issue192(Field_1) values (1), (2), (3); -SELECT * FROM @Issue192 WHERE Field IN @Field AND Field_1 IN @Field_1", - new { Field = new[] { 1, 2 }, Field_1 = new[] { 2, 3 } }).Single(); - ((int)rows.Field).IsEqualTo(2); - ((int)rows.Field_1).IsEqualTo(2); - } - - public void Issue192_InParameterWorksWithSimilarNamesWithUnicode() - { - var rows = connection.Query(@" -declare @Issue192 table ( - Field INT NOT NULL PRIMARY KEY IDENTITY(1,1), - Field_1 INT NOT NULL); -insert @Issue192(Field_1) values (1), (2), (3); -SELECT * FROM @Issue192 WHERE Field IN @µ AND Field_1 IN @µµ", - new { µ = new[] { 1, 2 }, µµ = new[] { 2, 3 } }).Single(); - ((int)rows.Field).IsEqualTo(2); - ((int)rows.Field_1).IsEqualTo(2); - } - - class _ExplicitConstructors - { - public int Field { get; set; } - public int Field_1 { get; set; } - - private bool WentThroughProperConstructor; - - public _ExplicitConstructors() { } - - [ExplicitConstructor] - public _ExplicitConstructors(string foo, int bar) - { - WentThroughProperConstructor = true; - } - - public bool GetWentThroughProperConstructor() - { - return WentThroughProperConstructor; - } - } - - public void ExplicitConstructors() - { - var rows = connection.Query<_ExplicitConstructors>(@" -declare @ExplicitConstructors table ( - Field INT NOT NULL PRIMARY KEY IDENTITY(1,1), - Field_1 INT NOT NULL); -insert @ExplicitConstructors(Field_1) values (1); -SELECT * FROM @ExplicitConstructors" -).ToList(); - - rows.Count.IsEqualTo(1); - rows[0].Field.IsEqualTo(1); - rows[0].Field_1.IsEqualTo(1); - rows[0].GetWentThroughProperConstructor().IsTrue(); - } - - public void Issue220_InParameterCanBeSpecifiedInAnyCase() - { - // note this might fail if your database server is case-sensitive - connection.Query("select * from (select 1 as Id) as X where Id in @ids", new { Ids = new[] { 1 } }) - .IsSequenceEqualTo(new[] { 1 }); - } - + [Fact] public void SO29343103_UtcDates() { const string sql = "select @date"; @@ -4444,6 +2761,7 @@ public void SO29343103_UtcDates() #if DOTNET5_2 [FrameworkFail("https://github.com/dotnet/corefx/issues/1612")] #endif + [Fact] public void Issue261_Decimals() { var parameters = new DynamicParameters(); @@ -4456,11 +2774,13 @@ public void Issue261_Decimals() #if DOTNET5_2 [FrameworkFail("https://github.com/dotnet/corefx/issues/1612")] #endif + [Fact] public void Issue261_Decimals_ADONET_SetViaBaseClass() { Issue261_Decimals_ADONET(true); } + [Fact] public void Issue261_Decimals_ADONET_SetViaConcreteClass() { Issue261_Decimals_ADONET(false); @@ -4506,11 +2826,13 @@ private void Issue261_Decimals_ADONET(bool setPrecisionScaleViaAbstractApi) } } + [Fact] public void BasicDecimals() { var c = connection.Query("select @c", new { c = 11.884M }).Single(); c.IsEqualTo(11.884M); } + [SkipTest] public void Issue263_Timeout() { @@ -4522,6 +2844,7 @@ public void Issue263_Timeout() Assert.IsTrue(minutes >= 0.95 && minutes <= 1.05); } #if EXTERNALS + [Fact] public void SO29596645_TvpProperty() { try { connection.Execute("CREATE TYPE SO29596645_ReminderRuleType AS TABLE (id int NOT NULL)"); } @@ -4536,28 +2859,6 @@ public void SO29596645_TvpProperty() } #endif - 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"); - retVal.IsEqualTo(3); - } #if EXTERNALS class SO29596645_RuleTableValuedParameters : Dapper.SqlMapper.IDynamicParameters { private string parameterName; @@ -4612,7 +2913,8 @@ class Cat new Cat() { Breed = "Javanese", Name="MADISON"}, new Cat() { Breed = "Persian", Name="MAGNA"} }; - + + [Fact] public void TestPostresqlArrayParameters() { using (var conn = new NpgsqlConnection("Server=localhost;Port=5432;User Id=dappertest;Password=dapperpass;Database=dappertest;Encoding=UNICODE")) @@ -4632,14 +2934,7 @@ public void TestPostresqlArrayParameters() } #endif - public void SO30156367_DynamicParamsWithoutExec() - { - var dbParams = new DynamicParameters(); - dbParams.Add("Field1", 1); - var value = dbParams.Get("Field1"); - value.IsEqualTo(1); - } - + [Fact] public void SO30435185_InvalidTypeOwner() { try { diff --git a/Dapper.DNX.Tests/project.json b/Dapper.DNX.Tests/project.json index c5eab3a89f42daa3dbfea963b1466adbf176b8dd..e50d6b3fb1cc876583e8079a59b03a6bb793112b 100644 --- a/Dapper.DNX.Tests/project.json +++ b/Dapper.DNX.Tests/project.json @@ -11,26 +11,32 @@ "target": "project" } }, - "commands": { - "Dapper.DNX.Tests": "Dapper.DNX.Tests" + "Dapper.DNX.Tests": "Dapper.DNX.Tests", + "test": "xunit.runner.dnx" }, - "frameworks": { "net45": { "compilationOptions": { - "define": [ ], + "define": [ "ASYNC" ], "warningsAsErrors": true }, "frameworkAssemblies": { "System.Data": "4.0.0.0", + "System.Runtime": "4.0.0.0", "System.Xml": "4.0.0.0" + }, + "dependencies": { + "xunit": "2.1.0" } }, "net40": { "frameworkAssemblies": { "System.Data": "4.0.0.0", "System.Xml": "4.0.0.0" + }, + "dependencies": { + "xunit": "1.9.2" } }, "dotnet5.2": { @@ -44,8 +50,27 @@ "System.Console": "4.0.0-beta-23409", "System.Data.SqlClient": "4.0.0-beta-23225", "System.Linq": "4.0.1-beta-23225", - "System.Threading": "4.0.11-beta-23225" + "System.Threading": "4.0.11-beta-23225", + "xunit": "2.1.0" + } + }, + "dnx451": { + "compilationOptions": { + "define": [ "ASYNC" ] + }, + "dependencies": { + "xunit": "2.1.0", + "xunit.runner.dnx": "2.1.0-rc1-build204" + } + }, + "dnxcore50": { + "compilationOptions": { + "define": [ "DOTNET5_2", "ASYNC" ] + }, + "dependencies": { + "xunit": "2.1.0", + "xunit.runner.dnx": "2.1.0-rc1-build204" } } } -} +} \ No newline at end of file