zoukankan      html  css  js  c++  java
  • Dapper full example

    Skip to content
    Sign up Sign in
    This repository  
    Explore
    Features
    Enterprise
    Blog
     Watch 390  Star 2,538  Fork 844 StackExchange/dapper-dot-net
     branch: master  dapper-dot-net/Tests/Tests.cs
    @mgravellmgravell 5 days ago SO30435185; make it clearer if the caller is passing an array (etc) w…
    21 contributors @mgravell @invalid-email-address @vosen @SamSaffron @jamesholwell @azhmur @jkonecki @brannon @teamyudin @markjerz @simonkang @kevin-montrose @johnleegrant @mrange @tms @fbdegroot @tuespetre @greygeek @RichCzyzewski @matwilko @xps
    RawBlameHistory     4615 lines (4028 sloc)  178.799 kb
    //#define POSTGRESQL // uncomment to run postgres tests
    
    #if DNXCORE50
    using IDbCommand = global::System.Data.Common.DbCommand;
    using IDbDataParameter = global::System.Data.Common.DbParameter;
    using IDbConnection = global::System.Data.Common.DbConnection;
    using IDbTransaction = global::System.Data.Common.DbTransaction;
    using IDataReader = global::System.Data.Common.DbDataReader;
    #endif
    
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Linq;
    using Dapper;
    using System.IO;
    using System.Data;
    using System.Collections;
    using System.Reflection;
    using System.Dynamic;
    using System.ComponentModel;
    using Microsoft.CSharp.RuntimeBinder;
    using System.Data.Common;
    using System.Globalization;
    using System.Threading;
    using System.Data.SqlTypes;
    using System.Diagnostics;
    
    #if EXTERNALS
    using FirebirdSql.Data.FirebirdClient;
    using System.Data.Entity.Spatial;
    using Microsoft.SqlServer.Types;
    using System.Data.SqlServerCe;
    #if POSTGRESQL
    using Npgsql;
    #endif
    #endif
    
    #if DNXCORE50
    namespace System.ComponentModel {
        public sealed class DescriptionAttribute : Attribute {
            public DescriptionAttribute(string description)
            {
                Description = description;
            }
            public string Description {get;private set;}
        }
    }
    namespace System
    {   
        public enum GenericUriParserOptions
        {
            Default
        }
        public class GenericUriParser
        {
            private GenericUriParserOptions options;
    
            public GenericUriParser(GenericUriParserOptions options)
            {
                this.options = options;
            }
        }
    }
    #endif
    
    namespace SqlMapper
    {
    
        class Tests
        {
            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 { get { return 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<PostWithConstructor, UserWithConstructor, PostWithConstructor>(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<MultipleConstructors>("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<ConstructorsWithAccessModifiers>("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; }
            }
    
            public void TestNoDefaultConstructor()
            {
                var guid = Guid.NewGuid();
                NoDefaultConstructor nodef = connection.Query<NoDefaultConstructor>("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<NoDefaultConstructorWithChar>("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; }
            }
    
            public void TestNoDefaultConstructorWithEnum()
            {
                NoDefaultConstructorWithEnum nodef = connection.Query<NoDefaultConstructorWithEnum>("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()
            {
                byte[] orig = new byte[20];
                new Random(123456).NextBytes(orig);
                var input = new System.Data.Linq.Binary(orig);
                var output = connection.Query<NoDefaultConstructorWithBinary>("select @input as val", new { input }).First().Value;
                output.ToArray().IsSequenceEqualTo(orig);
            }
    #endif
    
            // http://stackoverflow.com/q/8593871
            public void TestAbstractInheritance()
            {
                var order = connection.Query<AbstractInheritance.ConcreteOrder>("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);
            }
    
            public void TestListOfAnsiStrings()
            {
                var results = connection.Query<string>("select * from (select 'a' str union select 'b' union select 'c') X where str in @strings",
                    new { strings = new[] { new DbString { IsAnsi = true, Value = "a" }, new DbString { IsAnsi = true, Value = "b" } } }).ToList();
    
                results[0].IsEqualTo("a");
                results[1].IsEqualTo("b");
            }
    
            public void TestNullableGuidSupport()
            {
                var guid = connection.Query<Guid?>("select null").First();
                guid.IsNull();
    
                guid = Guid.NewGuid();
                var guid2 = connection.Query<Guid?>("select @guid", new { guid }).First();
                guid.IsEqualTo(guid2);
            }
    
            public void TestNonNullableGuidSupport()
            {
                var guid = Guid.NewGuid();
                var guid2 = connection.Query<Guid?>("select @guid", new { guid }).First();
                Assert.IsTrue(guid == guid2);
            }
    
            struct Car
            {
                public enum TrapEnum : int
                {
                    A = 1,
                    B = 2
                }
    #pragma warning disable 0649
                public string Name;
    #pragma warning restore 0649
                public int Age { get; set; }
                public TrapEnum Trap { get; set; }
    
            }
    
            struct CarWithAllProps
            {
                public string Name { get; set; }
                public int Age { get; set; }
    
                public Car.TrapEnum Trap { get; set; }
            }
    
            public void TestStructs()
            {
                var car = connection.Query<Car>("select 'Ford' Name, 21 Age, 2 Trap").First();
    
                car.Age.IsEqualTo(21);
                car.Name.IsEqualTo("Ford");
                ((int)car.Trap).IsEqualTo(2);
            }
    
            public void TestStructAsParam()
            {
                var car1 = new CarWithAllProps { Name = "Ford", Age = 21, Trap = Car.TrapEnum.B };
                // note Car has Name as a field; parameters only respect properties at the moment
                var car2 = connection.Query<CarWithAllProps>("select @Name Name, @Age Age, @Trap Trap", car1).First();
    
                car2.Name.IsEqualTo(car1.Name);
                car2.Age.IsEqualTo(car1.Age);
                car2.Trap.IsEqualTo(car1.Trap);
            }
    
            public void SelectListInt()
            {
                connection.Query<int>("select 1 union all select 2 union all select 3")
                  .IsSequenceEqualTo(new[] { 1, 2, 3 });
            }
            public void SelectBinary()
            {
                connection.Query<byte[]>("select cast(1 as varbinary(4))").First().SequenceEqual(new byte[] { 1 });
            }
            public void PassInIntArray()
            {
                connection.Query<int>("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 });
            }
    
            public void PassInEmptyIntArray()
            {
                connection.Query<int>("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]);
            }
    
            public void TestSchemaChanged()
            {
                connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
                try
                {
                    var d = connection.Query<Dog>("select * from #dog").Single();
                    d.Name.IsEqualTo("Alf");
                    d.Age.IsEqualTo(1);
                    connection.Execute("alter table #dog drop column Name");
                    d = connection.Query<Dog>("select * from #dog").Single();
                    d.Name.IsNull();
                    d.Age.IsEqualTo(1);
                }
                finally
                {
                    connection.Execute("drop table #dog");
                }
            }
    
            public void TestSchemaChangedMultiMap()
            {
                connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
                try
                {
                    var tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single();
    
                    tuple.Item1.Name.IsEqualTo("Alf");
                    tuple.Item1.Age.IsEqualTo(1);
                    tuple.Item2.Name.IsEqualTo("Alf");
                    tuple.Item2.Age.IsEqualTo(1);
    
                    connection.Execute("alter table #dog drop column Name");
                    tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single();
    
                    tuple.Item1.Name.IsNull();
                    tuple.Item1.Age.IsEqualTo(1);
                    tuple.Item2.Name.IsNull();
                    tuple.Item2.Age.IsEqualTo(1);
                }
                finally
                {
                    connection.Execute("drop table #dog");
                }
            }
    
            public void TestReadMultipleIntegersWithSplitOnAny()
            {
                connection.Query<int, int, int, Tuple<int, int, int>>(
                    "select 1,2,3 union all select 4,5,6", Tuple.Create, splitOn: "*")
                 .IsSequenceEqualTo(new[] { Tuple.Create(1, 2, 3), Tuple.Create(4, 5, 6) });
            }
    
            public void TestDoubleParam()
            {
                connection.Query<double>("select @d", new { d = 0.1d }).First()
                    .IsEqualTo(0.1d);
            }
    
            public void TestBoolParam()
            {
                connection.Query<bool>("select @b", new { b = false }).First()
                    .IsFalse();
            }
    
            // 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
            public void TestTimeSpanParam()
            {
                connection.Query<TimeSpan>("select @ts", new { ts = TimeSpan.FromMinutes(42) }).First()
                    .IsEqualTo(TimeSpan.FromMinutes(42));
            }
    
            public void TestStrings()
            {
                connection.Query<string>(@"select 'a' a union select 'b'")
                    .IsSequenceEqualTo(new[] { "a", "b" });
            }
    
            // see http://stackoverflow.com/questions/16726709/string-format-with-sql-wildcard-causing-dapper-query-to-break
            public void CheckComplexConcat()
            {
                string end_wildcard = @"
    SELECT * FROM #users16726709
    WHERE (first_name LIKE CONCAT(@search_term, '%') OR last_name LIKE CONCAT(@search_term, '%'));";
    
                string both_wildcards = @"
    SELECT * FROM #users16726709
    WHERE (first_name LIKE CONCAT('%', @search_term, '%') OR last_name LIKE CONCAT('%', @search_term, '%'));";
    
                string formatted = @"
    SELECT * FROM #users16726709
    WHERE (first_name LIKE {0} OR last_name LIKE {0});";
    
                string use_end_only = @"CONCAT(@search_term, '%')";
                string use_both = @"CONCAT('%', @search_term, '%')";
    
                // if true, slower query due to not being able to use indices, but will allow searching inside strings 
                bool allow_start_wildcards = false;
    
                string query = String.Format(formatted, allow_start_wildcards ? use_both : use_end_only);
                string term = "F"; // the term the user searched for
    
                connection.Execute(@"create table #users16726709 (first_name varchar(200), last_name varchar(200))
    insert #users16726709 values ('Fred','Bloggs') insert #users16726709 values ('Tony','Farcus') insert #users16726709 values ('Albert','TenoF')");
    
                // Using Dapper
                connection.Query(end_wildcard, new { search_term = term }).Count().IsEqualTo(2);
                connection.Query(both_wildcards, new { search_term = term }).Count().IsEqualTo(3);
                connection.Query(query, new { search_term = term }).Count().IsEqualTo(2);
    
            }
    
            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<EnumParamObject>("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<EnumParamObjectNonNullable>("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; }
                public Guid Id { get; set; }
                public string Name { get; set; }
                public float? Weight { get; set; }
    
                public int IgnoredProperty { get { return 1; } }
            }
    
            public void TestExtraFields()
            {
                var guid = Guid.NewGuid();
                var dog = connection.Query<Dog>("select '' as Extra, 1 as Age, 0.1 as Name1 , Id = @id", new { id = guid });
    
                dog.Count()
                   .IsEqualTo(1);
    
                dog.First().Age
                    .IsEqualTo(1);
    
                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
            public void TestStrongType()
            {
                var guid = Guid.NewGuid();
                var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
    
                dog.Count()
                    .IsEqualTo(1);
    
                dog.First().Age
                    .IsNull();
    
                dog.First().Id
                    .IsEqualTo(guid);
            }
    
            public void TestSimpleNull()
            {
                connection.Query<DateTime?>("select null").First().IsNull();
            }
    
            public void TestExpando()
            {
                var rows = connection.Query("select 1 A, 2 B union all select 3, 4").ToList();
    
                ((int)rows[0].A)
                    .IsEqualTo(1);
    
                ((int)rows[0].B)
                    .IsEqualTo(2);
    
                ((int)rows[1].A)
                    .IsEqualTo(3);
    
                ((int)rows[1].B)
                    .IsEqualTo(4);
            }
    
            public void TestStringList()
            {
                connection.Query<string>("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" } })
                    .IsSequenceEqualTo(new[] { "a", "b", "c" });
    
                connection.Query<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new { strings = new string[0] })
                       .IsSequenceEqualTo(new string[0]);
            }
    
            public void TestExecuteCommand()
            {
                connection.Execute(@"
        set nocount on 
        create table #t(i int) 
        set nocount off 
        insert #t 
        select @a a union all select @b 
        set nocount on 
        drop table #t", new { a = 1, b = 2 }).IsEqualTo(2);
            }
            public void TestExecuteCommandWithHybridParameters()
            {
                var p = new DynamicParameters(new { a = 1, b = 2 });
                p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.Output);
                connection.Execute(@"set @c = @a + @b", p);
                p.Get<int>("@c").IsEqualTo(3);
            }
            public void TestExecuteMultipleCommand()
            {
                connection.Execute("create table #t(i int)");
                try
                {
                    int tally = connection.Execute(@"insert #t (i) values(@a)", new[] { new { a = 1 }, new { a = 2 }, new { a = 3 }, new { a = 4 } });
                    int sum = connection.Query<int>("select sum(i) from #t").First();
                    tally.IsEqualTo(4);
                    sum.IsEqualTo(10);
                }
                finally
                {
                    connection.Execute("drop table #t");
                }
            }
    
            class Student
            {
                public string Name { get; set; }
                public int Age { get; set; }
            }
    
            public void TestExecuteMultipleCommandStrongType()
            {
                connection.Execute("create table #t(Name nvarchar(max), Age int)");
                try
                {
                    int tally = connection.Execute(@"insert #t (Name,Age) values(@Name, @Age)", new List<Student>
                {
                    new Student{Age = 1, Name = "sam"},
                    new Student{Age = 2, Name = "bob"}
                });
                    int sum = connection.Query<int>("select sum(Age) from #t").First();
                    tally.IsEqualTo(2);
                    sum.IsEqualTo(3);
                }
                finally
                {
                    connection.Execute("drop table #t");
                }
            }
    
            public void TestExecuteMultipleCommandObjectArray()
            {
                connection.Execute("create table #t(i int)");
                int tally = connection.Execute(@"insert #t (i) values(@a)", new object[] { new { a = 1 }, new { a = 2 }, new { a = 3 }, new { a = 4 } });
                int sum = connection.Query<int>("select sum(i) from #t drop table #t").First();
                tally.IsEqualTo(4);
                sum.IsEqualTo(10);
            }
    
            public void TestMassiveStrings()
            {
                var str = new string('X', 20000);
                connection.Query<string>("select @a", new { a = str }).First()
                    .IsEqualTo(str);
            }
    
            class TestObj
            {
                public int _internal;
                internal int Internal { set { _internal = value; } }
    
                public int _priv;
                private int Priv { set { _priv = value; } }
    
                private int PrivGet { get { return _priv; } }
            }
    
            public void TestSetInternal()
            {
                connection.Query<TestObj>("select 10 as [Internal]").First()._internal.IsEqualTo(10);
            }
    
            public void TestSetPrivate()
            {
                connection.Query<TestObj>("select 10 as [Priv]").First()._priv.IsEqualTo(10);
            }
    
    
            public void TestExpandWithNullableFields()
            {
                var row = connection.Query("select null A, 2 B").Single();
    
                ((int?)row.A)
                    .IsNull();
    
                ((int?)row.B)
                    .IsEqualTo(2);
            }
    
            public void TestEnumeration()
            {
                var en = connection.Query<int>("select 1 as one union all select 2 as one", buffered: false);
                var i = en.GetEnumerator();
                i.MoveNext();
    
                bool gotException = false;
                try
                {
                    var x = connection.Query<int>("select 1 as one", buffered: false).First();
                }
                catch (Exception)
                {
                    gotException = true;
                }
    
                while (i.MoveNext())
                { }
    
                // should not exception, since enumerated
                en = connection.Query<int>("select 1 as one", buffered: false);
    
                gotException.IsTrue();
            }
    
            public void TestEnumerationDynamic()
            {
                var en = connection.Query("select 1 as one union all select 2 as one", buffered: false);
                var i = en.GetEnumerator();
                i.MoveNext();
    
                bool gotException = false;
                try
                {
                    var x = connection.Query("select 1 as one", buffered: false).First();
                }
                catch (Exception)
                {
                    gotException = true;
                }
    
                while (i.MoveNext())
                { }
    
                // should not exception, since enumertated
                en = connection.Query("select 1 as one", buffered: false);
    
                gotException.IsTrue();
            }
    
            public void TestNakedBigInt()
            {
                long foo = 12345;
                var result = connection.Query<long>("select @foo", new { foo }).Single();
                foo.IsEqualTo(result);
            }
    
            public void TestBigIntMember()
            {
                long foo = 12345;
                var result = connection.Query<WithBigInt>(@"
    declare @bar table(Value bigint)
    insert @bar values (@foo)
    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<Post, User, Post>(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<object[], ReviewBoard> 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<ReviewBoard>(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>((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<int>();
                    var b = grid.Read<int>();
                    var c = grid.Read<int>();
                    var d = grid.Read<int>();
    
                    a.Single().Equals(1);
                    b.Single().Equals(2);
                    c.Single().Equals(3);
                    d.Single().Equals(4);
                }
            }
    
            public void TestQueryMultipleNonBufferedIncorrectOrder()
            {
                using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
                {
                    var a = grid.Read<int>(false);
                    try
                    {
                        var b = grid.Read<int>(false);
                        throw new InvalidOperationException(); // should have thrown
                    }
                    catch (InvalidOperationException)
                    {
                        // that's expected
                    }
    
                }
            }
            public void TestQueryMultipleNonBufferedCcorrectOrder()
            {
                using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
                {
                    var a = grid.Read<int>(false).Single();
                    var b = grid.Read<int>(false).Single();
                    var c = grid.Read<int>(false).Single();
                    var d = grid.Read<int>(false).Single();
    
                    a.Equals(1);
                    b.Equals(2);
                    c.Equals(3);
                    d.Equals(4);
                }
            }
            public void TestMultiMapDynamic()
            {
                var createSql = @"
                    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<dynamic, dynamic, dynamic>(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<Product, Category, Product>(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<Product, Category, Product>(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<Product, Category, Product>(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();
            }
            public void TestFieldsAndPrivates()
            {
                var data = connection.Query<TestFieldCaseAndPrivatesEntity>(
                    @"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
            public void ExecuteReader()
            {
                var dt = new DataTable();
                dt.Load(connection.ExecuteReader("select 3 as [three], 4 as [four]"));
                dt.Columns.Count.IsEqualTo(2);
                dt.Columns[0].ColumnName.IsEqualTo("three");
                dt.Columns[1].ColumnName.IsEqualTo("four");
                dt.Rows.Count.IsEqualTo(1);
                ((int)dt.Rows[0][0]).IsEqualTo(3);
                ((int)dt.Rows[0][1]).IsEqualTo(4);
            }
    #endif
            private class TestFieldCaseAndPrivatesEntity
            {
                public int a { get; set; }
                private int b { get; set; }
                public int GetB() { return b; }
                public int c = 0;
                private int d = 0;
                public int GetD() { return d; }
                public int e { get; set; }
                private string f
                {
                    get { return e.ToString(); }
                    set { e = int.Parse(value); }
                }
            }
    
            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<int>().First();
                    s = multi.Read<string>().Single();
                    j = multi.Read<int>().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<dynamic, dynamic, dynamic, dynamic>(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<dynamic, dynamic, dynamic, dynamic, dynamic>(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<dynamic, dynamic, dynamic, dynamic, dynamic, dynamic>(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; }
                public string Base2 { get; private set; }
            }
    
            class InheritanceTest2 : InheritanceTest1
            {
                public string Derived1 { get; set; }
                public string Derived2 { get; private set; }
            }
    
            public void TestInheritance()
            {
                // Test that inheritance works.
                var list = connection.Query<InheritanceTest2>("select 'One' as Derived1, 'Two' as Derived2, 'Three' as Base1, 'Four' as Base2");
                list.First().Derived1.IsEqualTo("One");
                list.First().Derived2.IsEqualTo("Two");
                list.First().Base1.IsEqualTo("Three");
                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
            public void MultiRSSqlCE()
            {
                if (File.Exists("Test.sdf"))
                    File.Delete("Test.sdf");
    
                var cnnStr = "Data Source = Test.sdf;";
                var engine = new SqlCeEngine(cnnStr);
                engine.CreateDatabase();
    
                using (var cnn = new SqlCeConnection(cnnStr))
                {
                    cnn.Open();
    
                    cnn.Execute("create table Posts (ID int, Title nvarchar(50), Body nvarchar(50), AuthorID int)");
                    cnn.Execute("create table Authors (ID int, Name nvarchar(50))");
    
                    cnn.Execute("insert Posts values (1,'title','body',1)");
                    cnn.Execute("insert Posts values(2,'title2','body2',null)");
                    cnn.Execute("insert Authors values(1,'sam')");
    
                    var data = cnn.Query<PostCE, AuthorCE, PostCE>(@"select * from Posts p left join Authors a on a.ID = p.AuthorID", (post, author) => { post.Author = author; return post; }).ToList();
                    var firstPost = data.First();
                    firstPost.Title.IsEqualTo("title");
                    firstPost.Author.Name.IsEqualTo("sam");
                    data[1].Author.IsNull();
                    cnn.Close();
                }
            }
    #endif
            enum TestEnum : byte
            {
                Bla = 1
            }
            class TestEnumClass
            {
                public TestEnum? EnumEnum { get; set; }
            }
            class TestEnumClassNoNull
            {
                public TestEnum EnumEnum { get; set; }
            }
            public void TestEnumWeirdness()
            {
                connection.Query<TestEnumClass>("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null);
                connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
            }
            public void TestEnumStrings()
            {
                connection.Query<TestEnumClassNoNull>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
                connection.Query<TestEnumClassNoNull>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
    
                connection.Query<TestEnumClass>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
                connection.Query<TestEnumClass>("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<string>("set @age = 11 select @name", p).First().IsEqualTo("bob");
    
                p.Get<int>("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<int>(@"
    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<int>(@"
    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<int>().Single();
                        y = multi.Read<int>().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<string>("select @name", parameters).First();
                result.IsEqualTo("bob");
            }
    
            public void TestProcSupport()
            {
                var p = new DynamicParameters();
                p.Add("a", 11);
                p.Add("b", dbType: DbType.Int32, direction: ParameterDirection.Output);
                p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
    
                connection.Execute(@"create proc #TestProc 
        @a int,
        @b int output
    as 
    begin
        set @b = 999
        select 1111
        return @a
    end");
                connection.Query<int>("#TestProc", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(1111);
    
                p.Get<int>("c").IsEqualTo(11);
                p.Get<int>("b").IsEqualTo(999);
    
            }
    
            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",
                    new
                    {
                        a = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true },
                        b = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = false },
                        c = new DbString { Value = "abcde", IsFixedLength = false, Length = 10, IsAnsi = true },
                        d = new DbString { Value = "abcde", IsFixedLength = false, Length = 10, IsAnsi = false },
                        e = new DbString { Value = "abcde", IsAnsi = true },
                        f = new DbString { Value = "abcde", IsAnsi = false },
                    }).First();
                ((int)obj.a).IsEqualTo(10);
                ((int)obj.b).IsEqualTo(20);
                ((int)obj.c).IsEqualTo(5);
                ((int)obj.d).IsEqualTo(10);
                ((int)obj.e).IsEqualTo(5);
                ((int)obj.f).IsEqualTo(10);
            }
    
            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<Person, Address, Extra, Tuple<Person, Address, Extra>>
                    (sql, (p, a, e) => Tuple.Create(p, a, e), 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<Person, Address, Extra, Tuple<Person, Address, Extra>>
                    (sql, (p, a, e) => Tuple.Create(p, a, e), 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<Post_DupeProp, Blog_DupeProp, Post_DupeProp>(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; }
            }
    
            public void TestFastExpandoSupportsIDictionary()
            {
                var row = connection.Query("select 1 A, 'two' B").First() as IDictionary<string, object>;
                row["A"].IsEqualTo(1);
                row["B"].IsEqualTo("two");
            }
    
    
            class PrivateDan
            {
                public int Shadow { get; set; }
                private string ShadowInDB
                {
                    set
                    {
                        Shadow = value == "one" ? 1 : 0;
                    }
                }
            }
            public void TestDapperSetsPrivates()
            {
                connection.Query<PrivateDan>("select 'one' ShadowInDB").First().Shadow.IsEqualTo(1);
            }
    
    
            class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters
            {
                IEnumerable<int> numbers;
                public IntDynamicParam(IEnumerable<int> numbers)
                {
                    this.numbers = numbers;
                }
    
                public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
                {
                    var sqlCommand = (SqlCommand)command;
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
    
                    // 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<int>("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<int> numbers;
                public DynamicParameterWithIntTVP(IEnumerable<int> 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<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
    
                    // 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<int> numbers;
                public IntCustomParam(IEnumerable<int> numbers)
                {
                    this.numbers = numbers;
                }
    
                public void AddParameter(IDbCommand command, string name)
                {
                    var sqlCommand = (SqlCommand)command;
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
    
                    // 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<int>("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<Child> Children = new List<Child>();
            }
            class Child
            {
                public int Id { get; set; }
            }
            public void ParentChildIdentityAssociations()
            {
                var lookup = new Dictionary<int, Parent>();
                var parents = connection.Query<Parent, Child, Parent>(@"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:
             * 
            public void TestMagicParam()
            {
                // magic params allow you to pass in single params without using an anon class
                // this test fails for now, but I would like to support a single param by parsing the sql with regex and remapping. 
                var first = connection.Query("select @a as a", 1).First();
                Assert.IsEqualTo(first.a, 1);
            }
             * */
    
            class WithBizarreData
            {
                public GenericUriParser Foo { get; set; }
                public int Bar { get; set; }
            }
    
            public void TestUnexpectedDataMessage()
            {
                string msg = null;
                try
                {
                    connection.Query<int>("select count(1) where 1 = @Foo", new WithBizarreData { Foo = new GenericUriParser(GenericUriParserOptions.Default), Bar = 23 }).First();
    
                }
                catch (Exception ex)
                {
                    msg = ex.Message;
                }
                msg.IsEqualTo("The member Foo of type System.GenericUriParser cannot be used as a parameter value");
            }
    
            public void TestUnexpectedButFilteredDataMessage()
            {
                int i = connection.Query<int>("select @Bar", new WithBizarreData { Foo = new GenericUriParser(GenericUriParserOptions.Default), Bar = 23 }).Single();
    
                i.IsEqualTo(23);
            }
    
            class WithCharValue
            {
                public char Value { get; set; }
                public char? ValueNullable { get; set; }
            }
            public void TestCharInputAndOutput()
            {
                const char test = '';
                char c = connection.Query<char>("select @c", new { c = test }).Single();
    
                c.IsEqualTo(test);
    
                var obj = connection.Query<WithCharValue>("select @Value as Value", new WithCharValue { Value = c }).Single();
    
                obj.Value.IsEqualTo(test);
            }
            public void TestNullableCharInputAndOutputNonNull()
            {
                char? test = '';
                char? c = connection.Query<char?>("select @c", new { c = test }).Single();
    
                c.IsEqualTo(test);
    
                var obj = connection.Query<WithCharValue>("select @ValueNullable as ValueNullable", new WithCharValue { ValueNullable = c }).Single();
    
                obj.ValueNullable.IsEqualTo(test);
            }
            public void TestNullableCharInputAndOutputNull()
            {
                char? test = null;
                char? c = connection.Query<char?>("select @c", new { c = test }).Single();
    
                c.IsEqualTo(test);
    
                var obj = connection.Query<WithCharValue>("select @ValueNullable as ValueNullable", new WithCharValue { ValueNullable = c }).Single();
    
                obj.ValueNullable.IsEqualTo(test);
            }
            public void TestInvalidSplitCausesNiceError()
            {
                try
                {
                    connection.Query<User, User, User>("select 1 A, 2 B, 3 C", (x, y) => x);
                }
                catch (ArgumentException)
                {
                    // expecting an app exception due to multi mapping being bodged 
                }
    
                try
                {
                    connection.Query<dynamic, dynamic, dynamic>("select 1 A, 2 B, 3 C", (x, y) => x);
                }
                catch (ArgumentException)
                {
                    // expecting an app exception due to multi mapping being bodged 
                }
            }
    
    
    
            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<Post>().ToList();
    
                    var post2 = grid.Read<Post, User, Comment, Post>((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<IDbDataParameter>
            {
                private readonly List<IDbDataParameter> parameters = new List<IDbDataParameter>();
                public IEnumerator<IDbDataParameter> 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);
    
                }
            }
            public void TestCustomParameters()
            {
                var args = new DbParams {
                    new SqlParameter("foo", 123),
                    new SqlParameter("bar", "abc")
                };
                var result = connection.Query("select Foo=@foo, Bar=@bar", args).Single();
                int foo = result.Foo;
                string bar = result.Bar;
                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");
                }
            }
    
            public void TestDynamicParamNullSupport()
            {
                var p = new DynamicParameters();
    
                p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
                connection.Execute("select @b = null", p);
    
                p.Get<int?>("@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<Foo1, Bar1, Tuple<Foo1, Bar1>>("select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name", (f, b) => Tuple.Create(f, b), 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
            public void TestLinqBinaryToClass()
            {
                byte[] orig = new byte[20];
                new Random(123456).NextBytes(orig);
                var input = new System.Data.Linq.Binary(orig);
    
                var output = connection.Query<WithBinary>("select @input as [Value]", new { input }).First().Value;
    
                output.ToArray().IsSequenceEqualTo(orig);
            }
    
            public void TestLinqBinaryRaw()
            {
                byte[] orig = new byte[20];
                new Random(123456).NextBytes(orig);
                var input = new System.Data.Linq.Binary(orig);
    
                var output = connection.Query<System.Data.Linq.Binary>("select @input as [Value]", new { input }).First();
    
                output.ToArray().IsSequenceEqualTo(orig);
            }
    
            class WithBinary
            {
                public System.Data.Linq.Binary Value { get; set; }
            }
    #endif
    
            class WithPrivateConstructor
            {
                public int Foo { get; set; }
                private WithPrivateConstructor() { }
            }
    
            public void TestWithNonPublicConstructor()
            {
                var output = connection.Query<WithPrivateConstructor>("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<string, object>();
                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<int>("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<string, object>();
                args.Add("ids", list);
                p.AddDynamicParams(args);
    
                var result = connection.Query<int>("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<int>("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<Guid>("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<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
                result.IsEqualTo(guid);
            }
            public void TestNullableUniqueIdentifierNull()
            {
                Guid? guid = null;
                var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
                result.IsEqualTo(guid);
            }
    
    
            public void WorkDespiteHavingWrongStructColumnTypes()
            {
                var hazInt = connection.Query<CanHazInt>("select cast(1 as bigint) Value").Single();
                hazInt.Value.Equals(1);
            }
    
    
            public void TestProcWithOutParameter()
            {
                connection.Execute(
                    @"CREATE PROCEDURE #TestProcWithOutParameter
            @ID int output,
            @Foo varchar(100),
            @Bar int
            AS
            SET @ID = @Bar + LEN(@Foo)");
                var obj = new
                {
                    ID = 0,
                    Foo = "abc",
                    Bar = 4
                };
                var args = new DynamicParameters(obj);
                args.Add("ID", 0, direction: ParameterDirection.Output);
                connection.Execute("#TestProcWithOutParameter", args, commandType: CommandType.StoredProcedure);
                args.Get<int>("ID").IsEqualTo(7);
            }
            public void TestProcWithOutAndReturnParameter()
            {
                connection.Execute(
                    @"CREATE PROCEDURE #TestProcWithOutAndReturnParameter
            @ID int output,
            @Foo varchar(100),
            @Bar int
            AS
            SET @ID = @Bar + LEN(@Foo)
            RETURN 42");
                var obj = new
                {
                    ID = 0,
                    Foo = "abc",
                    Bar = 4
                };
                var args = new DynamicParameters(obj);
                args.Add("ID", 0, direction: ParameterDirection.Output);
                args.Add("result", 0, direction: ParameterDirection.ReturnValue);
                connection.Execute("#TestProcWithOutAndReturnParameter", args, commandType: CommandType.StoredProcedure);
                args.Get<int>("ID").IsEqualTo(7);
                args.Get<int>("result").IsEqualTo(42);
            }
            struct CanHazInt
            {
                public int Value { get; set; }
            }
            public void TestInt16Usage()
            {
                connection.Query<short>("select cast(42 as smallint)").Single().IsEqualTo((short)42);
                connection.Query<short?>("select cast(42 as smallint)").Single().IsEqualTo((short?)42);
                connection.Query<short?>("select cast(null as smallint)").Single().IsEqualTo((short?)null);
    
                connection.Query<ShortEnum>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum)42);
                connection.Query<ShortEnum?>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum?)42);
                connection.Query<ShortEnum?>("select cast(null as smallint)").Single().IsEqualTo((ShortEnum?)null);
    
                var row =
                    connection.Query<WithInt16Values>(
                        "select cast(1 as smallint) as NonNullableInt16, cast(2 as smallint) as NullableInt16, cast(3 as smallint) as NonNullableInt16Enum, cast(4 as smallint) as NullableInt16Enum")
                        .Single();
                row.NonNullableInt16.IsEqualTo((short)1);
                row.NullableInt16.IsEqualTo((short)2);
                row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Three);
                row.NullableInt16Enum.IsEqualTo(ShortEnum.Four);
    
                row =
        connection.Query<WithInt16Values>(
            "select cast(5 as smallint) as NonNullableInt16, cast(null as smallint) as NullableInt16, cast(6 as smallint) as NonNullableInt16Enum, cast(null as smallint) as NullableInt16Enum")
            .Single();
                row.NonNullableInt16.IsEqualTo((short)5);
                row.NullableInt16.IsEqualTo((short?)null);
                row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Six);
                row.NullableInt16Enum.IsEqualTo((ShortEnum?)null);
            }
            public void TestInt32Usage()
            {
                connection.Query<int>("select cast(42 as int)").Single().IsEqualTo((int)42);
                connection.Query<int?>("select cast(42 as int)").Single().IsEqualTo((int?)42);
                connection.Query<int?>("select cast(null as int)").Single().IsEqualTo((int?)null);
    
                connection.Query<IntEnum>("select cast(42 as int)").Single().IsEqualTo((IntEnum)42);
                connection.Query<IntEnum?>("select cast(42 as int)").Single().IsEqualTo((IntEnum?)42);
                connection.Query<IntEnum?>("select cast(null as int)").Single().IsEqualTo((IntEnum?)null);
    
                var row =
                    connection.Query<WithInt32Values>(
                        "select cast(1 as int) as NonNullableInt32, cast(2 as int) as NullableInt32, cast(3 as int) as NonNullableInt32Enum, cast(4 as int) as NullableInt32Enum")
                        .Single();
                row.NonNullableInt32.IsEqualTo((int)1);
                row.NullableInt32.IsEqualTo((int)2);
                row.NonNullableInt32Enum.IsEqualTo(IntEnum.Three);
                row.NullableInt32Enum.IsEqualTo(IntEnum.Four);
    
                row =
        connection.Query<WithInt32Values>(
            "select cast(5 as int) as NonNullableInt32, cast(null as int) as NullableInt32, cast(6 as int) as NonNullableInt32Enum, cast(null as int) as NullableInt32Enum")
            .Single();
                row.NonNullableInt32.IsEqualTo((int)5);
                row.NullableInt32.IsEqualTo((int?)null);
                row.NonNullableInt32Enum.IsEqualTo(IntEnum.Six);
                row.NullableInt32Enum.IsEqualTo((IntEnum?)null);
            }
    
            public class WithInt16Values
            {
                public short NonNullableInt16 { get; set; }
                public short? NullableInt16 { get; set; }
                public ShortEnum NonNullableInt16Enum { get; set; }
                public ShortEnum? NullableInt16Enum { get; set; }
            }
            public enum ShortEnum : short
            {
                Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
            }
            public class WithInt32Values
            {
                public int NonNullableInt32 { get; set; }
                public int? NullableInt32 { get; set; }
                public IntEnum NonNullableInt32Enum { get; set; }
                public IntEnum? NullableInt32Enum { get; set; }
            }
            public enum IntEnum : int
            {
                Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
            }
    
            public void TestTransactionCommit()
            {
                try
                {
                    connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
    
                    using (var transaction = connection.BeginTransaction())
                    {
                        connection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');", transaction: transaction);
    
                        transaction.Commit();
                    }
    
                    connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(1);
                }
                finally
                {
                    connection.Execute("drop table #TransactionTest;");
                }
            }
    
            public void TestTransactionRollback()
            {
                connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
    
                try
                {
                    using (var transaction = connection.BeginTransaction())
                    {
                        connection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');", transaction: transaction);
    
                        transaction.Rollback();
                    }
    
                    connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(0);
                }
                finally
                {
                    connection.Execute("drop table #TransactionTest;");
                }
            }
    
            public void TestCommandWithInheritedTransaction()
            {
                connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
    
                try
                {
                    using (var transaction = connection.BeginTransaction())
                    {
                        var transactedConnection = new TransactedConnection(connection, transaction);
    
                        transactedConnection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');");
    
                        transaction.Rollback();
                    }
    
                    connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(0);
                }
                finally
                {
                    connection.Execute("drop table #TransactionTest;");
                }
            }
    
            public void TestReaderWhenResultsChange()
            {
                try
                {
    
                    connection.Execute("create table #ResultsChange (X int);create table #ResultsChange2 (Y int);insert #ResultsChange (X) values(1);insert #ResultsChange2 (Y) values(1);");
    
                    var obj1 = connection.Query<ResultsChangeType>("select * from #ResultsChange").Single();
                    obj1.X.IsEqualTo(1);
                    obj1.Y.IsEqualTo(0);
                    obj1.Z.IsEqualTo(0);
    
                    var obj2 = connection.Query<ResultsChangeType>("select * from #ResultsChange rc inner join #ResultsChange2 rc2 on rc2.Y=rc.X").Single();
                    obj2.X.IsEqualTo(1);
                    obj2.Y.IsEqualTo(1);
                    obj2.Z.IsEqualTo(0);
    
                    connection.Execute("alter table #ResultsChange add Z int null");
                    connection.Execute("update #ResultsChange set Z = 2");
    
                    var obj3 = connection.Query<ResultsChangeType>("select * from #ResultsChange").Single();
                    obj3.X.IsEqualTo(1);
                    obj3.Y.IsEqualTo(0);
                    obj3.Z.IsEqualTo(2);
    
                    var obj4 = connection.Query<ResultsChangeType>("select * from #ResultsChange rc inner join #ResultsChange2 rc2 on rc2.Y=rc.X").Single();
                    obj4.X.IsEqualTo(1);
                    obj4.Y.IsEqualTo(1);
                    obj4.Z.IsEqualTo(2);
                }
                finally
                {
                    connection.Execute("drop table #ResultsChange;drop table #ResultsChange2;");
                }
            }
            class ResultsChangeType
            {
                public int X { get; set; }
                public int Y { get; set; }
                public int Z { get; set; }
            }
    
            public void TestCustomTypeMap()
            {
                // default mapping
                var item = connection.Query<TypeWithMapping>("Select 'AVal' as A, 'BVal' as B").Single();
                item.A.IsEqualTo("AVal");
                item.B.IsEqualTo("BVal");
    
                // custom mapping
                var map = new CustomPropertyTypeMap(typeof(TypeWithMapping),
                    (type, columnName) => type.GetProperties().Where(prop => GetDescriptionFromAttribute(prop) == columnName).FirstOrDefault());
                Dapper.SqlMapper.SetTypeMap(typeof(TypeWithMapping), map);
    
                item = connection.Query<TypeWithMapping>("Select 'AVal' as A, 'BVal' as B").Single();
                item.A.IsEqualTo("BVal");
                item.B.IsEqualTo("AVal");
    
                // reset to default
                Dapper.SqlMapper.SetTypeMap(typeof(TypeWithMapping), null);
                item = connection.Query<TypeWithMapping>("Select 'AVal' as A, 'BVal' as B").Single();
                item.A.IsEqualTo("AVal");
                item.B.IsEqualTo("BVal");
            }
            static string GetDescriptionFromAttribute(MemberInfo member)
            {
                if (member == null) return null;
    #if DNXCORE50
                var data = member.CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(DescriptionAttribute));
                return data == null ? null : (string)data.ConstructorArguments.Single().Value;
    #else
                var attrib = (DescriptionAttribute)Attribute.GetCustomAttribute(member, typeof(DescriptionAttribute), false);
                return attrib == null ? null : attrib.Description;
    #endif
            }
            public class TypeWithMapping
            {
                [Description("B")]
                public string A { get; set; }
    
                [Description("A")]
                public string B { get; set; }
            }
    
            public class WrongTypes
            {
                public int A { get; set; }
                public double B { get; set; }
                public long C { get; set; }
                public bool D { get; set; }
            }
    
            public void TestWrongTypes_WithRightTypes()
            {
                var item = connection.Query<WrongTypes>("select 1 as A, cast(2.0 as float) as B, cast(3 as bigint) as C, cast(1 as bit) as D").Single();
                item.A.Equals(1);
                item.B.Equals(2.0);
                item.C.Equals(3L);
                item.D.Equals(true);
            }
    
            public void TestWrongTypes_WithWrongTypes()
            {
                var item = connection.Query<WrongTypes>("select cast(1.0 as float) as A, 2 as B, 3 as C, cast(1 as bigint) as D").Single();
                item.A.Equals(1);
                item.B.Equals(2.0);
                item.C.Equals(3L);
                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<int>("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<int>("#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<MultipleParametersWithIndexer>("select 1 A,2 B").First();
    
                order.A.IsEqualTo(1);
                order.B.IsEqualTo(2);
            }
    
            public void Issue_40_AutomaticBoolConversion()
            {
                var user = connection.Query<Issue40_User>("select UserId=1,Email='abc',Password='changeme',Active=cast(1 as tinyint)").Single();
                user.Active.IsTrue();
                user.UserID.IsEqualTo(1);
                user.Email.IsEqualTo("abc");
                user.Password.IsEqualTo("changeme");
            }
    
            public class Issue40_User
            {
                public Issue40_User()
                {
                    Email = Password = String.Empty;
                }
                public int UserID { get; set; }
                public string Email { get; set; }
                public string Password { get; set; }
                public bool Active { get; set; }
            }
    
            SqlConnection GetClosedConnection()
            {
                var conn = new SqlConnection(connection.ConnectionString);
                if (conn.State != ConnectionState.Closed) throw new InvalidOperationException("should be closed!");
                return conn;
            }
            public void ExecuteFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    conn.Execute("-- nop");
                    conn.State.IsEqualTo(ConnectionState.Closed);
                }
            }
            class Multi1
            {
                public int Id { get; set; }
            }
            class Multi2
            {
                public int Id { get; set; }
            }
            public void QueryMultimapFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    conn.State.IsEqualTo(ConnectionState.Closed);
                    var i = conn.Query<Multi1, Multi2, int>("select 2 as [Id], 3 as [Id]", (x, y) => x.Id + y.Id).Single();
                    conn.State.IsEqualTo(ConnectionState.Closed);
                    i.IsEqualTo(5);
                }
            }
            public void QueryMultiple2FromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    conn.State.IsEqualTo(ConnectionState.Closed);
                    using (var multi = conn.QueryMultiple("select 1 select 2 select 3"))
                    {
                        multi.Read<int>().Single().IsEqualTo(1);
                        multi.Read<int>().Single().IsEqualTo(2);
                        // not reading 3 is intentional here
                    }
                    conn.State.IsEqualTo(ConnectionState.Closed);
                }
            }
            public void ExecuteInvalidFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    try
                    {
                        conn.Execute("nop");
                        false.IsEqualTo(true); // shouldn't have got here
                    }
                    catch
                    {
                        conn.State.IsEqualTo(ConnectionState.Closed);
                    }
                }
            }
            public void QueryFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    var i = conn.Query<int>("select 1").Single();
                    conn.State.IsEqualTo(ConnectionState.Closed);
                    i.IsEqualTo(1);
                }
            }
            public void QueryInvalidFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    try
                    {
                        conn.Query<int>("select gibberish").Single();
                        false.IsEqualTo(true); // shouldn't have got here
                    }
                    catch
                    {
                        conn.State.IsEqualTo(ConnectionState.Closed);
                    }
                }
            }
            public void QueryMultipleFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    using (var multi = conn.QueryMultiple("select 1; select 'abc';"))
                    {
                        multi.Read<int>().Single().IsEqualTo(1);
                        multi.Read<string>().Single().IsEqualTo("abc");
                    }
                    conn.State.IsEqualTo(ConnectionState.Closed);
                }
            }
            public void QueryMultipleInvalidFromClosed()
            {
                using (var conn = GetClosedConnection())
                {
                    try
                    {
                        conn.QueryMultiple("select gibberish");
                        false.IsEqualTo(true); // shouldn't have got here
                    }
                    catch
                    {
                        conn.State.IsEqualTo(ConnectionState.Closed);
                    }
                }
            }
    
            public void TestMultiSelectWithSomeEmptyGrids()
            {
                using (var reader = connection.QueryMultiple("select 1; select 2 where 1 = 0; select 3 where 1 = 0; select 4;"))
                {
                    var one = reader.Read<int>().ToArray();
                    var two = reader.Read<int>().ToArray();
                    var three = reader.Read<int>().ToArray();
                    var four = reader.Read<int>().ToArray();
                    try
                    { // only returned four grids; expect a fifth read to fail
                        reader.Read<int>();
                        throw new InvalidOperationException("this should not have worked!");
                    }
                    catch (ObjectDisposedException ex)
                    { // expected; success
                        ex.Message.IsEqualTo("The reader has been disposed; this can happen after all data has been consumed
    Object name: 'Dapper.SqlMapper+GridReader'.");
                    }
    
                    one.Length.IsEqualTo(1);
                    one[0].IsEqualTo(1);
                    two.Length.IsEqualTo(0);
                    three.Length.IsEqualTo(0);
                    four.Length.IsEqualTo(1);
                    four[0].IsEqualTo(4);
                }
            }
    
            public void TestDynamicMutation()
            {
                var obj = connection.Query("select 1 as [a], 2 as [b], 3 as [c]").Single();
                ((int)obj.a).IsEqualTo(1);
                IDictionary<string, object> dict = obj;
                Assert.Equals(3, dict.Count);
                Assert.IsTrue(dict.Remove("a"));
                Assert.IsFalse(dict.Remove("d"));
                Assert.Equals(2, dict.Count);
                dict.Add("d", 4);
                Assert.Equals(3, dict.Count);
                Assert.Equals("b,c,d", string.Join(",", dict.Keys.OrderBy(x => x)));
                Assert.Equals("2,3,4", string.Join(",", dict.OrderBy(x => x.Key).Select(x => x.Value)));
    
                Assert.Equals(2, (int)obj.b);
                Assert.Equals(3, (int)obj.c);
                Assert.Equals(4, (int)obj.d);
                try
                {
                    ((int)obj.a).IsEqualTo(1);
                    throw new InvalidOperationException("should have thrown");
                }
                catch (RuntimeBinderException)
                {
                    // pass
                }
            }
    
            public void TestIssue131()
            {
                var results = connection.Query<dynamic, int, dynamic>(
                    "SELECT 1 Id, 'Mr' Title, 'John' Surname, 4 AddressCount",
                    (person, addressCount) =>
                    {
                        return person;
                    },
                    splitOn: "AddressCount"
                ).FirstOrDefault();
    
                var asDict = (IDictionary<string, object>)results;
    
                asDict.ContainsKey("Id").IsEqualTo(true);
                asDict.ContainsKey("Title").IsEqualTo(true);
                asDict.ContainsKey("Surname").IsEqualTo(true);
                asDict.ContainsKey("AddressCount").IsEqualTo(false);
            }
            // see http://stackoverflow.com/questions/16955357/issue-about-dapper
            public void TestSplitWithMissingMembers()
            {
                var result = connection.Query<Topic, Profile, Topic>(
                @"select 123 as ID, 'abc' as Title,
                         cast('01 Feb 2013' as datetime) as CreateDate,
                         'ghi' as Name, 'def' as Phone",
                (T, P) => { T.Author = P; return T; },
                null, null, true, "ID,Name").Single();
    
                result.ID.Equals(123);
                result.Title.Equals("abc");
                result.CreateDate.Equals(new DateTime(2013, 2, 1));
                result.Name.IsNull();
                result.Content.IsNull();
    
                result.Author.Phone.Equals("def");
                result.Author.Name.Equals("ghi");
                result.Author.ID.Equals(0);
                result.Author.Address.IsNull();
            }
            public class Profile
            {
                public int ID { get; set; }
                public string Name { get; set; }
                public string Phone { get; set; }
                public string Address { get; set; }
                //public ExtraInfo Extra { get; set; }
            }
    
            public class Topic
            {
                public int ID { get; set; }
                public string Title { get; set; }
                public DateTime CreateDate { get; set; }
                public string Content { get; set; }
                public int UID { get; set; }
                public int TestColum { get; set; }
                public string Name { get; set; }
                public Profile Author { get; set; }
                //public Attachment Attach { get; set; }
            }
    
            // see http://stackoverflow.com/questions/13127886/dapper-returns-null-for-singleordefaultdatediff
            public void TestNullFromInt_NoRows()
            {
                var result = connection.Query<int>( // case with rows
                 "select DATEDIFF(day, GETUTCDATE(), @date)", new { date = DateTime.UtcNow.AddDays(20) })
                 .SingleOrDefault();
                result.IsEqualTo(20);
    
                result = connection.Query<int>( // case without rows
                    "select DATEDIFF(day, GETUTCDATE(), @date) where 1 = 0", new { date = DateTime.UtcNow.AddDays(20) })
                    .SingleOrDefault();
                result.IsEqualTo(0); // zero rows; default of int over zero rows is zero
    
    
            }
    
            public void TestChangingDefaultStringTypeMappingToAnsiString()
            {
                var sql = "SELECT SQL_VARIANT_PROPERTY(CONVERT(sql_variant, @testParam),'BaseType') AS BaseType";
                var param = new { testParam = "TestString" };
    
                var result01 = connection.Query<string>(sql, param).FirstOrDefault();
                result01.IsEqualTo("nvarchar");
    
                Dapper.SqlMapper.PurgeQueryCache();
    
                Dapper.SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString);   // Change Default String Handling to AnsiString
                var result02 = connection.Query<string>(sql, param).FirstOrDefault();
                result02.IsEqualTo("varchar");
    
                Dapper.SqlMapper.PurgeQueryCache();
                Dapper.SqlMapper.AddTypeMap(typeof(string), DbType.String);  // Restore Default to Unicode String
            }
    #if DNXCORE50
            class TransactedConnection : IDbConnection
            {
                IDbConnection _conn;
                IDbTransaction _tran;
    
                public TransactedConnection(IDbConnection conn, IDbTransaction tran)
                {
                    _conn = conn;
                    _tran = tran;
                }
    
                public override string ConnectionString { get { return _conn.ConnectionString; } set { _conn.ConnectionString = value; } }
                public override int ConnectionTimeout { get { return _conn.ConnectionTimeout; } }
                public override string Database { get { return _conn.Database; } }
                public override ConnectionState State { get { return _conn.State; } }
    
                protected override IDbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
                {
                    return _tran;
                }
                
                public override void ChangeDatabase(string databaseName)
                {
                    _conn.ChangeDatabase(databaseName);
                }
                public override string DataSource
                {
                    get
                    {
                        return _conn.DataSource;
                    }
                }
                public override string ServerVersion
                {
                    get
                    {
                        return _conn.ServerVersion;
                    }
                }
                public override void Close()
                {
                    _conn.Close();
                }
                protected override IDbCommand CreateDbCommand()
                {
                    // The command inherits the "current" transaction.
                    var command = _conn.CreateCommand();
                    command.Transaction = _tran;
                    return command;
                }
    
                protected override void Dispose(bool disposing)
                {
                    if(disposing) _conn.Dispose();
                    base.Dispose(disposing);
                }
    
                public override void Open()
                {
                    _conn.Open();
                }
            }
    #else
            class TransactedConnection : IDbConnection
            {
                IDbConnection _conn;
                IDbTransaction _tran;
    
                public TransactedConnection(IDbConnection conn, IDbTransaction tran)
                {
                    _conn = conn;
                    _tran = tran;
                }
    
                public string ConnectionString { get { return _conn.ConnectionString; } set { _conn.ConnectionString = value; } }
                public int ConnectionTimeout { get { return _conn.ConnectionTimeout; } }
                public string Database { get { return _conn.Database; } }
                public ConnectionState State { get { return _conn.State; } }
    
                public IDbTransaction BeginTransaction(IsolationLevel il)
                {
                    throw new NotImplementedException();
                }
    
                public IDbTransaction BeginTransaction()
                {
                    return _tran;
                }
    
                public void ChangeDatabase(string databaseName)
                {
                    _conn.ChangeDatabase(databaseName);
                }
    
                public void Close()
                {
                    _conn.Close();
                }
    
                public IDbCommand CreateCommand()
                {
                    // The command inherits the "current" transaction.
                    var command = _conn.CreateCommand();
                    command.Transaction = _tran;
                    return command;
                }
    
                public void Dispose()
                {
                    _conn.Dispose();
                }
    
                public void Open()
                {
                    _conn.Open();
                }
            }
    #endif
            public void TestDapperTableMetadataRetrieval()
            {
                // Test for a bug found in CS 51509960 where the following sequence would result in an InvalidOperationException being
                // thrown due to an attempt to access a disposed of DataReader:
                //
                // - Perform a dynamic query that yields no results
                // - Add data to the source of that query
                // - Perform a the same query again
                connection.Execute("CREATE TABLE #sut (value varchar(10) NOT NULL PRIMARY KEY)");
                connection.Query("SELECT value FROM #sut").IsSequenceEqualTo(Enumerable.Empty<dynamic>());
    
                connection.Execute("INSERT INTO #sut (value) VALUES ('test')").IsEqualTo(1);
                var result = connection.Query("SELECT value FROM #sut");
    
                var first = result.First();
                ((string)first.value).IsEqualTo("test");
            }
    
            public void TestIssue17648290()
            {
                var p = new DynamicParameters();
                int code = 1, getMessageControlId = 2;
                p.Add("@Code", code);
                p.Add("@MessageControlID", getMessageControlId);
                p.Add("@SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
                p.Add("@ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
                connection.Execute(@"CREATE PROCEDURE #up_MessageProcessed_get
            @Code varchar(10),
            @MessageControlID varchar(22),
            @SuccessCode int OUTPUT,
            @ErrorDescription varchar(255) OUTPUT
            AS
            BEGIN
            Select 2 as MessageProcessID, 38349348 as StartNum, 3874900 as EndNum, GETDATE() as StartDate, GETDATE() as EndDate
            SET @SuccessCode = 0
            SET @ErrorDescription = 'Completed successfully'
            END");
                var result = connection.Query(sql: "#up_MessageProcessed_get", param: p, commandType: CommandType.StoredProcedure);
                var row = result.Single();
                ((int)row.MessageProcessID).IsEqualTo(2);
                ((int)row.StartNum).IsEqualTo(38349348);
                ((int)row.EndNum).IsEqualTo(3874900);
                DateTime startDate = row.StartDate, endDate = row.EndDate;
                p.Get<int>("SuccessCode").IsEqualTo(0);
                p.Get<string>("ErrorDescription").IsEqualTo("Completed successfully");
            }
    
            public void TestDoubleDecimalConversions_SO18228523_RightWay()
            {
                var row = connection.Query<HasDoubleDecimal>(
                    "select cast(1 as float) as A, cast(2 as float) as B, cast(3 as decimal) as C, cast(4 as decimal) as D").Single();
                row.A.Equals(1.0);
                row.B.Equals(2.0);
                row.C.Equals(3.0M);
                row.D.Equals(4.0M);
            }
            public void TestDoubleDecimalConversions_SO18228523_WrongWay()
            {
                var row = connection.Query<HasDoubleDecimal>(
                    "select cast(1 as decimal) as A, cast(2 as decimal) as B, cast(3 as float) as C, cast(4 as float) as D").Single();
                row.A.Equals(1.0);
                row.B.Equals(2.0);
                row.C.Equals(3.0M);
                row.D.Equals(4.0M);
            }
            public void TestDoubleDecimalConversions_SO18228523_Nulls()
            {
                var row = connection.Query<HasDoubleDecimal>(
                    "select cast(null as decimal) as A, cast(null as decimal) as B, cast(null as float) as C, cast(null as float) as D").Single();
                row.A.Equals(0.0);
                row.B.IsNull();
                row.C.Equals(0.0M);
                row.D.IsNull();
            }
            private static CultureInfo ActiveCulture
            {
    #if DNXCORE50
                get { return CultureInfo.CurrentCulture; }
                set { CultureInfo.CurrentCulture = value; }
    #else
                get { return Thread.CurrentThread.CurrentCulture; }
                set { Thread.CurrentThread.CurrentCulture = value; }
    #endif
            }
            public void TestParameterInclusionNotSensitiveToCurrentCulture()
            {
                // note this might fail if your database server is case-sensitive
                CultureInfo current = ActiveCulture;
                try
                {
                    ActiveCulture = new CultureInfo("tr-TR");
    
                    connection.Query<int>("select @pid", new { PId = 1 }).Single();
                }
                finally
                {
                    ActiveCulture = current;
                }
            }
            public void LiteralReplacement()
            {
                connection.Execute("create table #literal1 (id int not null, foo int not null)");
                connection.Execute("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.Execute("insert #literal1 (id,foo) values ({=id}, @foo)", rows);
                var count = connection.Query<int>("select count(1) from #literal1 where id={=foo}", new { foo = 123 }).Single();
                count.IsEqualTo(1);
                int sum = connection.Query<int>("select sum(id) + sum(foo) from #literal1").Single();
                sum.IsEqualTo(123 + 456 + 1 + 2 + 3 + 4);
            }
            public void LiteralReplacementDynamic()
            {
                var args = new DynamicParameters();
                args.Add("id", 123);
                connection.Execute("create table #literal2 (id int not null)");
                connection.Execute("insert #literal2 (id) values ({=id})", args);
    
                args = new DynamicParameters();
                args.Add("foo", 123);
                var count = connection.Query<int>("select count(1) from #literal2 where id={=foo}", args).Single();
                count.IsEqualTo(1);
            }
    
            enum AnEnum
            {
                A = 2,
                B = 1
            }
            enum AnotherEnum : byte
            {
                A = 2,
                B = 1
            }
    
    #if DNXCORE50
            [FrameworkFail("https://github.com/dotnet/corefx/issues/1613")]
    #endif
            public void AdoNetEnumValue()
            {
                using (var cmd = connection.CreateCommand())
                {
                    cmd.CommandText = "select @foo";
                    cmd.Parameters.AddWithValue("@foo", AnEnum.B);
                    object value = cmd.ExecuteScalar();
                    AnEnum val = (AnEnum)value;
                    val.IsEqualTo(AnEnum.B);
                }
            }
    
            public void LiteralReplacementEnumAndString()
            {
                var args = new { x = AnEnum.B, y = 123.45M, z = AnotherEnum.A };
                var row = connection.Query("select {=x} as x,{=y} as y,cast({=z} as tinyint) as z", args).Single();
                AnEnum x = (AnEnum)(int)row.x;
                decimal y = row.y;
                AnotherEnum z = (AnotherEnum)(byte)row.z;
                x.Equals(AnEnum.B);
                y.Equals(123.45M);
                z.Equals(AnotherEnum.A);
            }
    
            public void LiteralReplacementDynamicEnumAndString()
            {
                var args = new DynamicParameters();
                args.Add("x", AnEnum.B);
                args.Add("y", 123.45M);
                args.Add("z", AnotherEnum.A);
                var row = connection.Query("select {=x} as x,{=y} as y,cast({=z} as tinyint) as z", args).Single();
                AnEnum x = (AnEnum)(int)row.x;
                decimal y = row.y;
                AnotherEnum z = (AnotherEnum)(byte)row.z;
                x.Equals(AnEnum.B);
                y.Equals(123.45M);
                z.Equals(AnotherEnum.A);
            }
            
            public void LiteralReplacementBoolean()
            {
                var row = connection.Query<int?>("select 42 where 1 = {=val}", new { val = true }).SingleOrDefault();
                row.IsNotNull();
                row.IsEqualTo(42);
                row = connection.Query<int?>("select 42 where 1 = {=val}", new { val = false }).SingleOrDefault();
                row.IsNull();
            }
            public void LiteralReplacementWithIn()
            {
                var data = connection.Query<MyRow>("select @x where 1 in @ids and 1 ={=a}",
                    new { x = 1, ids = new[] { 1, 2, 3 }, a = 1 }).ToList();
            }
    
            class MyRow
            {
                public int x { get; set; }
            }
    
            public void LiteralIn()
            {
                connection.Execute("create table #literalin(id int not null);");
                connection.Execute("insert #literalin (id) values (@id)", new[] {
                    new { id = 1 },
                    new { id = 2 },
                    new { id = 3 },
                });
                var count = connection.Query<int>("select count(1) from #literalin where id in {=ids}",
                    new { ids = new[] { 1, 3, 4 } }).Single();
                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<int>(sql, new { vals = new[] { 1, 2, 3, 4 } }).Single();
                count.IsEqualTo(2);
    
                count = connection.Query<int>(sql, new { vals = new[] { 1 } }).Single();
                count.IsEqualTo(1);
    
                count = connection.Query<int>(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<TimeSpan>("#TestProcWithTimeParameter", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(new TimeSpan(10, 0, 0));
            }
    
            public void DbString()
            {
                var a = connection.Query<int>("select datalength(@x)",
                    new { x = new DbString { Value = "abc", IsAnsi = true } }).Single();
                var b = connection.Query<int>("select datalength(@x)",
                    new { x = new DbString { Value = "abc", IsAnsi = false } }).Single();
                a.IsEqualTo(3);
                b.IsEqualTo(6);
            }
    
            class HasInt32
            {
                public int Value { get; set; }
            }
            // http://stackoverflow.com/q/23696254/23354
            public void DownwardIntegerConversion()
            {
                const string sql = "select cast(42 as bigint) as Value";
                int i = connection.Query<HasInt32>(sql).Single().Value;
                Assert.IsEqualTo(42, i);
    
                i = connection.Query<int>(sql).Single();
                Assert.IsEqualTo(42, i);
            }
    
            class HasDoubleDecimal
            {
                public double A { get; set; }
                public double? B { get; set; }
                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<int>("#DataTableParameters", new { ids = table.AsTableValuedParameter() }, commandType: CommandType.StoredProcedure).First();
                count.IsEqualTo(3);
    
                count = connection.Query<int>("select count(1) from @ids", new { ids = table.AsTableValuedParameter("MyTVPType") }).First();
                count.IsEqualTo(3);
    
                try
                {
                    connection.Query<int>("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<string, object> args = new Dictionary<string, object>();
                args.Add("ids", table);
                int count = connection.Query<int>("#DataTableParameters", args, commandType: CommandType.StoredProcedure).First();
                count.IsEqualTo(3);
    
                count = connection.Query<int>("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<int>(@"
                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<int>("#DataTableParameters", new { ids = table }, commandType: CommandType.StoredProcedure).First();
                count.IsEqualTo(3);
    
                count = connection.Query<int>("select count(1) from @ids", new { ids = table }).First();
                count.IsEqualTo(3);
    
                try
                {
                    connection.Query<int>("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<WithInit>("select 'abc' as Value").Single();
                obj.Value.Equals("abc");
                obj.Flags.Equals(31);
            }
    #endif
            public void GuidIn_SO_24177902()
            {
                // invent and populate
                Guid a = Guid.NewGuid(), b = Guid.NewGuid(), c = Guid.NewGuid(), d = Guid.NewGuid();
                connection.Execute("create table #foo (i int, g uniqueidentifier)");
                connection.Execute("insert #foo(i,g) values(@i,@g)",
                    new[] { new { i = 1, g = a }, new { i = 2, g = b },
                    new { i = 3, g = c },new { i = 4, g = d }});
    
                // check that rows 2&3 yield guids b&c
                var guids = connection.Query<Guid>("select g from #foo where i in (2,3)").ToArray();
                guids.Length.Equals(2);
                guids.Contains(a).Equals(false);
                guids.Contains(b).Equals(true);
                guids.Contains(c).Equals(true);
                guids.Contains(d).Equals(false);
    
                // in query on the guids
                var rows = connection.Query("select * from #foo where g in @guids order by i", new { guids })
                    .Select(row => new { i = (int)row.i, g = (Guid)row.g }).ToArray();
                rows.Length.Equals(2);
                rows[0].i.Equals(2);
                rows[0].g.Equals(b);
                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<HazGeo>("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<HazSqlGeo>("select * from #SqlGeo where id=1").SingleOrDefault();
                row.IsNotNull();
                row.Id.IsEqualTo(1);
                row.Geo.IsNotNull();
                row.Geometry.IsNotNull();
            }
    
            public void SqlHierarchyId_SO18888911()
            {
                Dapper.SqlMapper.ResetTypeHandlers();
                var row = connection.Query<HazSqlHierarchy>("select 3 as [Id], hierarchyid::Parse('/1/2/3/') as [Path]").Single();
                row.Id.Equals(3);
                row.Path.IsNotNull();
    
                var val = connection.Query<SqlHierarchyId>("select @Path", row).Single();
                val.IsNotNull();
            }
    
            public class HazSqlHierarchy
            {
                public int Id { get; set; }
                public SqlHierarchyId Path { get; set; }
            }
    #endif
            public void TypeBasedViaDynamic()
            {
                Type type = GetSomeType();
    
                dynamic template = Activator.CreateInstance(type);
                dynamic actual = CheetViaDynamic(template, "select @A as [A], @B as [B]", new { A = 123, B = "abc" });
                ((object)actual).GetType().IsEqualTo(type);
                int a = actual.A;
                string b = actual.B;
                a.IsEqualTo(123);
                b.IsEqualTo("abc");
            }
            public void TypeBasedViaType()
            {
                Type type = GetSomeType();
    
                dynamic actual = connection.Query(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;
                a.IsEqualTo(123);
                b.IsEqualTo("abc");
            }
            public void TypeBasedViaTypeMulti()
            {
                Type type = GetSomeType();
    
                dynamic first, second;
                using (var multi = connection.QueryMultiple("select @A as [A], @B as [B]; select @C as [A], @D as [B]",
                    new { A = 123, B = "abc", C = 456, D = "def" }))
                {
                    first = multi.Read(type).Single();
                    second = multi.Read(type).Single();
                }
                ((object)first).GetType().IsEqualTo(type);
                int a = first.A;
                string b = first.B;
                a.IsEqualTo(123);
                b.IsEqualTo("abc");
    
                ((object)second).GetType().IsEqualTo(type);
                a = second.A;
                b = second.B;
                a.IsEqualTo(456);
                b.IsEqualTo("def");
            }
            T CheetViaDynamic<T>(T template, string query, object args)
            {
                return connection.Query<T>(query, args).SingleOrDefault();
            }
            static Type GetSomeType()
            {
                return typeof(SomeType);
            }
            public class SomeType
            {
                public int A { get; set; }
                public string B { get; set; }
            }
    #if !DNXCORE50
            class WithInit : ISupportInitialize
            {
                public string Value { get; set; }
                public int Flags { get; set; }
    
                void ISupportInitialize.BeginInit()
                {
                    Flags += 1;
                }
    
                void ISupportInitialize.EndInit()
                {
                    Flags += 30;
                }
            }
    #endif
            public void SO24607639_NullableBools()
            {
                var obj = connection.Query<HazBools>(
                    @"declare @vals table (A bit null, B bit null, C bit null);
                    insert @vals (A,B,C) values (1,0,null);
                    select * from @vals").Single();
                obj.IsNotNull();
                obj.A.Value.IsEqualTo(true);
                obj.B.Value.IsEqualTo(false);
                obj.C.IsNull();
            }
            class HazBools
            {
                public bool? A { get; set; }
                public bool? B { get; set; }
                public bool? C { get; set; }
            }
    
            public void SO24605346_ProcsAndStrings()
            {
                connection.Execute(@"create proc #GetPracticeRebateOrderByInvoiceNumber @TaxInvoiceNumber nvarchar(20) as
                    select @TaxInvoiceNumber as [fTaxInvoiceNumber]");
                string InvoiceNumber = "INV0000000028PPN";
                var result = connection.Query<PracticeRebateOrders>("#GetPracticeRebateOrderByInvoiceNumber", new
                {
                    TaxInvoiceNumber = InvoiceNumber
                }, commandType: CommandType.StoredProcedure).FirstOrDefault();
    
                result.TaxInvoiceNumber.IsEqualTo("INV0000000028PPN");
            }
            class PracticeRebateOrders
            {
                public string fTaxInvoiceNumber;
    #if EXTERNALS
                [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    #endif
                public string TaxInvoiceNumber { get { return fTaxInvoiceNumber; } set { fTaxInvoiceNumber = value; } }
            }
    
            public class RatingValueHandler : Dapper.SqlMapper.TypeHandler<RatingValue>
            {
                private RatingValueHandler() { }
                public static readonly RatingValueHandler Default = new RatingValueHandler();
                public override RatingValue Parse(object value)
                {
                    if (value is Int32)
                        return new RatingValue() { Value = (Int32)value };
    
                    throw new FormatException("Invalid conversion to RatingValue");
                }
    
                public override void SetValue(IDbDataParameter parameter, RatingValue value)
                {
                    // ... null, range checks etc ...
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = value.Value;
                }
            }
            public class RatingValue
            {
                public Int32 Value { get; set; }
                // ... some other properties etc ...
            }
    
            public class MyResult
            {
                public String CategoryName { get; set; }
                public RatingValue CategoryRating { get; set; }
            }
    
            public void SO24740733_TestCustomValueHandler()
            {
                Dapper.SqlMapper.AddTypeHandler(RatingValueHandler.Default);
                var foo = connection.Query<MyResult>("SELECT 'Foo' AS CategoryName, 200 AS CategoryRating").Single();
    
                foo.CategoryName.IsEqualTo("Foo");
                foo.CategoryRating.Value.IsEqualTo(200);
            }
    
            enum SO27024806Enum { Foo, Bar }
    
            private class SO27024806Class
            {
                public SO27024806Class(SO27024806Enum myField)
                {
                    this.MyField = myField;
                }
    
                public SO27024806Enum MyField { get; set; }
            }
    
            public void SO27024806_TestVarcharEnumMemberWithExplicitConstructor()
            {
                var foo = connection.Query<SO27024806Class>("SELECT 'Foo' AS myField").Single();
                foo.MyField.IsEqualTo(SO27024806Enum.Foo);
            }
    
    
            public void SO24740733_TestCustomValueSingleColumn()
            {
                Dapper.SqlMapper.AddTypeHandler(RatingValueHandler.Default);
                var foo = connection.Query<RatingValue>("SELECT 200 AS CategoryRating").Single();
    
                foo.Value.IsEqualTo(200);
            }
    
            public void Issue130_IConvertible()
            {
                dynamic row = connection.Query("select 1 as [a], '2' as [b]").Single();
                int a = row.a;
                string b = row.b;
                a.IsEqualTo(1);
                b.IsEqualTo("2");
    
                row = connection.Query<dynamic>("select 3 as [a], '4' as [b]").Single();
                a = row.a;
                b = row.b;
                a.IsEqualTo(3);
                b.IsEqualTo("4");
            }
    
            public void Issue22_ExecuteScalar()
            {
                int i = connection.ExecuteScalar<int>("select 123");
                i.IsEqualTo(123);
    
                i = connection.ExecuteScalar<int>("select cast(123 as bigint)");
                i.IsEqualTo(123);
    
                long j = connection.ExecuteScalar<long>("select 123");
                j.IsEqualTo(123L);
    
                j = connection.ExecuteScalar<long>("select cast(123 as bigint)");
                j.IsEqualTo(123L);
    
                int? k = connection.ExecuteScalar<int?>("select @i", new { i = default(int?) });
                k.IsNull();
    
    #if EXTERNALS
                Dapper.EntityFramework.Handlers.Register();
                var geo = DbGeography.LineFromText("LINESTRING(-122.360 47.656, -122.343 47.656 )", 4326);
                var geo2 = connection.ExecuteScalar<DbGeography>("select @geo", new { geo });
                geo2.IsNotNull();
    #endif
            }
    
            public void Issue142_FailsNamedStatus()
            {
                var row1 = connection.Query<Issue142_Status>("select @Status as [Status]", new { Status = StatusType.Started }).Single();
                row1.Status.IsEqualTo(StatusType.Started);
    
                var row2 = connection.Query<Issue142_StatusType>("select @Status as [Status]", new { Status = Status.Started }).Single();
                row2.Status.IsEqualTo(Status.Started);
            }
    
            public class Issue142_Status
            {
                public StatusType Status { get; set; }
            }
            public class Issue142_StatusType
            {
                public Status Status { get; set; }
            }
    
            public enum StatusType : byte
            {
                NotStarted = 1, Started = 2, Finished = 3
            }
            public enum Status : byte
            {
                NotStarted = 1, Started = 2, Finished = 3
            }
    
    
    
            public void Issue136_ValueTypeHandlers()
            {
                Dapper.SqlMapper.ResetTypeHandlers();
                Dapper.SqlMapper.AddTypeHandler(typeof(LocalDate), LocalDateHandler.Default);
                var param = new LocalDateResult
                {
                    NotNullable = new LocalDate { Year = 2014, Month = 7, Day = 25 },
                    NullableNotNull = new LocalDate { Year = 2014, Month = 7, Day = 26 },
                    NullableIsNull = null,
                };
    
                var result = connection.Query<LocalDateResult>("SELECT @NotNullable AS NotNullable, @NullableNotNull AS NullableNotNull, @NullableIsNull AS NullableIsNull", param).Single();
    
                Dapper.SqlMapper.ResetTypeHandlers();
                Dapper.SqlMapper.AddTypeHandler(typeof(LocalDate?), LocalDateHandler.Default);
                result = connection.Query<LocalDateResult>("SELECT @NotNullable AS NotNullable, @NullableNotNull AS NullableNotNull, @NullableIsNull AS NullableIsNull", param).Single();
            }
            public class LocalDateHandler : Dapper.SqlMapper.TypeHandler<LocalDate>
            {
                private LocalDateHandler() { }
    
                // Make the field type ITypeHandler to ensure it cannot be used with SqlMapper.AddTypeHandler<T>(TypeHandler<T>)
                // by mistake.
                public static readonly Dapper.SqlMapper.ITypeHandler Default = new LocalDateHandler();
    
                public override LocalDate Parse(object value)
                {
                    var date = (DateTime)value;
                    return new LocalDate { Year = date.Year, Month = date.Month, Day = date.Day };
                }
    
                public override void SetValue(IDbDataParameter parameter, LocalDate value)
                {
                    parameter.DbType = DbType.DateTime;
                    parameter.Value = new DateTime(value.Year, value.Month, value.Day);
                }
            }
    
            public struct LocalDate
            {
                public int Year { get; set; }
                public int Month { get; set; }
                public int Day { get; set; }
            }
    
            public class LocalDateResult
            {
                public LocalDate NotNullable { get; set; }
                public LocalDate? NullableNotNull { get; set; }
                public LocalDate? NullableIsNull { get; set; }
            }
    
            public class LotsOfNumerics
            {
                public enum E_Byte : byte { A = 0, B = 1 }
                public enum E_SByte : sbyte { A = 0, B = 1 }
                public enum E_Short : short { A = 0, B = 1 }
                public enum E_UShort : ushort { A = 0, B = 1 }
                public enum E_Int : int { A = 0, B = 1 }
                public enum E_UInt : uint { A = 0, B = 1 }
                public enum E_Long : long { A = 0, B = 1 }
                public enum E_ULong : ulong { A = 0, B = 1 }
    
                public E_Byte P_Byte { get; set; }
                public E_SByte P_SByte { get; set; }
                public E_Short P_Short { get; set; }
                public E_UShort P_UShort { get; set; }
                public E_Int P_Int { get; set; }
                public E_UInt P_UInt { get; set; }
                public E_Long P_Long { get; set; }
                public E_ULong P_ULong { get; set; }
    
                public bool N_Bool { get; set; }
                public byte N_Byte { get; set; }
                public sbyte N_SByte { get; set; }
                public short N_Short { get; set; }
                public ushort N_UShort { get; set; }
                public int N_Int { get; set; }
                public uint N_UInt { get; set; }
                public long N_Long { get; set; }
                public ulong N_ULong { get; set; }
    
                public float N_Float { get; set; }
                public double N_Double { get; set; }
                public decimal N_Decimal { get; set; }
    
                public E_Byte? N_P_Byte { get; set; }
                public E_SByte? N_P_SByte { get; set; }
                public E_Short? N_P_Short { get; set; }
                public E_UShort? N_P_UShort { get; set; }
                public E_Int? N_P_Int { get; set; }
                public E_UInt? N_P_UInt { get; set; }
                public E_Long? N_P_Long { get; set; }
                public E_ULong? N_P_ULong { get; set; }
    
                public bool? N_N_Bool { get; set; }
                public byte? N_N_Byte { get; set; }
                public sbyte? N_N_SByte { get; set; }
                public short? N_N_Short { get; set; }
                public ushort? N_N_UShort { get; set; }
                public int? N_N_Int { get; set; }
                public uint? N_N_UInt { get; set; }
                public long? N_N_Long { get; set; }
                public ulong? N_N_ULong { get; set; }
    
                public float? N_N_Float { get; set; }
                public double? N_N_Double { get; set; }
                public decimal? N_N_Decimal { get; set; }
            }
    
            public void TestBigIntForEverythingWorks_SqlLite()
            {
                TestBigIntForEverythingWorks_SqlLite_ByDataType<long>("bigint");
                TestBigIntForEverythingWorks_SqlLite_ByDataType<int>("int");
                TestBigIntForEverythingWorks_SqlLite_ByDataType<byte>("tinyint");
                TestBigIntForEverythingWorks_SqlLite_ByDataType<short>("smallint");
                TestBigIntForEverythingWorks_SqlLite_ByDataType<bool>("bit");
                TestBigIntForEverythingWorks_SqlLite_ByDataType<float>("float(24)");
                TestBigIntForEverythingWorks_SqlLite_ByDataType<double>("float(53)");
            }
            private void TestBigIntForEverythingWorks_SqlLite_ByDataType<T>(string dbType)
            {
                using (var reader = connection.ExecuteReader("select cast(1 as " + dbType + ")"))
                {
                    reader.Read().IsTrue();
                    reader.GetFieldType(0).Equals(typeof(T));
                    reader.Read().IsFalse();
                    reader.NextResult().IsFalse();
                }
    
                string sql = "select " + string.Join(",", typeof(LotsOfNumerics).GetProperties().Select(
                    x => "cast (1 as " + dbType + ") as [" + x.Name + "]"));
                var row = connection.Query<LotsOfNumerics>(sql).Single();
    
                row.N_Bool.IsTrue();
                row.N_SByte.IsEqualTo((sbyte)1);
                row.N_Byte.IsEqualTo((byte)1);
                row.N_Int.IsEqualTo((int)1);
                row.N_UInt.IsEqualTo((uint)1);
                row.N_Short.IsEqualTo((short)1);
                row.N_UShort.IsEqualTo((ushort)1);
                row.N_Long.IsEqualTo((long)1);
                row.N_ULong.IsEqualTo((ulong)1);
                row.N_Float.IsEqualTo((float)1);
                row.N_Double.IsEqualTo((double)1);
                row.N_Decimal.IsEqualTo((decimal)1);
    
                row.P_Byte.IsEqualTo(LotsOfNumerics.E_Byte.B);
                row.P_SByte.IsEqualTo(LotsOfNumerics.E_SByte.B);
                row.P_Short.IsEqualTo(LotsOfNumerics.E_Short.B);
                row.P_UShort.IsEqualTo(LotsOfNumerics.E_UShort.B);
                row.P_Int.IsEqualTo(LotsOfNumerics.E_Int.B);
                row.P_UInt.IsEqualTo(LotsOfNumerics.E_UInt.B);
                row.P_Long.IsEqualTo(LotsOfNumerics.E_Long.B);
                row.P_ULong.IsEqualTo(LotsOfNumerics.E_ULong.B);
    
                row.N_N_Bool.Value.IsTrue();
                row.N_N_SByte.Value.IsEqualTo((sbyte)1);
                row.N_N_Byte.Value.IsEqualTo((byte)1);
                row.N_N_Int.Value.IsEqualTo((int)1);
                row.N_N_UInt.Value.IsEqualTo((uint)1);
                row.N_N_Short.Value.IsEqualTo((short)1);
                row.N_N_UShort.Value.IsEqualTo((ushort)1);
                row.N_N_Long.Value.IsEqualTo((long)1);
                row.N_N_ULong.Value.IsEqualTo((ulong)1);
                row.N_N_Float.Value.IsEqualTo((float)1);
                row.N_N_Double.Value.IsEqualTo((double)1);
                row.N_N_Decimal.IsEqualTo((decimal)1);
    
                row.N_P_Byte.Value.IsEqualTo(LotsOfNumerics.E_Byte.B);
                row.N_P_SByte.Value.IsEqualTo(LotsOfNumerics.E_SByte.B);
                row.N_P_Short.Value.IsEqualTo(LotsOfNumerics.E_Short.B);
                row.N_P_UShort.Value.IsEqualTo(LotsOfNumerics.E_UShort.B);
                row.N_P_Int.Value.IsEqualTo(LotsOfNumerics.E_Int.B);
                row.N_P_UInt.Value.IsEqualTo(LotsOfNumerics.E_UInt.B);
                row.N_P_Long.Value.IsEqualTo(LotsOfNumerics.E_Long.B);
                row.N_P_ULong.Value.IsEqualTo(LotsOfNumerics.E_ULong.B);
    
                TestBigIntForEverythingWorks<bool>(true, dbType);
                TestBigIntForEverythingWorks<sbyte>((sbyte)1, dbType);
                TestBigIntForEverythingWorks<byte>((byte)1, dbType);
                TestBigIntForEverythingWorks<int>((int)1, dbType);
                TestBigIntForEverythingWorks<uint>((uint)1, dbType);
                TestBigIntForEverythingWorks<short>((short)1, dbType);
                TestBigIntForEverythingWorks<ushort>((ushort)1, dbType);
                TestBigIntForEverythingWorks<long>((long)1, dbType);
                TestBigIntForEverythingWorks<ulong>((ulong)1, dbType);
                TestBigIntForEverythingWorks<float>((float)1, dbType);
                TestBigIntForEverythingWorks<double>((double)1, dbType);
                TestBigIntForEverythingWorks<decimal>((decimal)1, dbType);
    
                TestBigIntForEverythingWorks(LotsOfNumerics.E_Byte.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_SByte.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_Int.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_UInt.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_Short.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_UShort.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_Long.B, dbType);
                TestBigIntForEverythingWorks(LotsOfNumerics.E_ULong.B, dbType);
    
                TestBigIntForEverythingWorks<bool?>(true, dbType);
                TestBigIntForEverythingWorks<sbyte?>((sbyte)1, dbType);
                TestBigIntForEverythingWorks<byte?>((byte)1, dbType);
                TestBigIntForEverythingWorks<int?>((int)1, dbType);
                TestBigIntForEverythingWorks<uint?>((uint)1, dbType);
                TestBigIntForEverythingWorks<short?>((short)1, dbType);
                TestBigIntForEverythingWorks<ushort?>((ushort)1, dbType);
                TestBigIntForEverythingWorks<long?>((long)1, dbType);
                TestBigIntForEverythingWorks<ulong?>((ulong)1, dbType);
                TestBigIntForEverythingWorks<float?>((float)1, dbType);
                TestBigIntForEverythingWorks<double?>((double)1, dbType);
                TestBigIntForEverythingWorks<decimal?>((decimal)1, dbType);
    
                TestBigIntForEverythingWorks<LotsOfNumerics.E_Byte?>(LotsOfNumerics.E_Byte.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_SByte?>(LotsOfNumerics.E_SByte.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_Int?>(LotsOfNumerics.E_Int.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_UInt?>(LotsOfNumerics.E_UInt.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_Short?>(LotsOfNumerics.E_Short.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_UShort?>(LotsOfNumerics.E_UShort.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_Long?>(LotsOfNumerics.E_Long.B, dbType);
                TestBigIntForEverythingWorks<LotsOfNumerics.E_ULong?>(LotsOfNumerics.E_ULong.B, dbType);
            }
    
            private void TestBigIntForEverythingWorks<T>(T expected, string dbType)
            {
                var query = connection.Query<T>("select cast(1 as " + dbType + ")").Single();
                query.IsEqualTo(expected);
    
                var scalar = connection.ExecuteScalar<T>("select cast(1 as " + dbType + ")");
                scalar.IsEqualTo(expected);
            }
    
            public void TestSubsequentQueriesSuccess()
            {
                var data0 = connection.Query<Fooz0>("select 1 as [Id] where 1 = 0").ToList();
                data0.Count().IsEqualTo(0);
    
                var data1 = connection.Query<Fooz1>(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered)).ToList();
                data1.Count().IsEqualTo(0);
    
                var data2 = connection.Query<Fooz2>(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None)).ToList();
                data2.Count().IsEqualTo(0);
    
                data0 = connection.Query<Fooz0>("select 1 as [Id] where 1 = 0").ToList();
                data0.Count().IsEqualTo(0);
    
                data1 = connection.Query<Fooz1>(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.Buffered)).ToList();
                data1.Count().IsEqualTo(0);
    
                data2 = connection.Query<Fooz2>(new CommandDefinition("select 1 as [Id] where 1 = 0", flags: CommandFlags.None)).ToList();
                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<HazX>("SO25069578", parameters,
                    commandType: CommandType.StoredProcedure, transaction: tran).Single();
                tran.Rollback();
                row.X.IsEqualTo("bar");
            }
    
            public void Issue149_TypeMismatch_SequentialAccess()
            {
                string error;
                Guid guid = Guid.Parse("cf0ef7ac-b6fe-4e24-aeda-a2b45bb5654e");
                try
                {
                    var result = connection.Query<Issue149_Person>(@"select @guid as Id", new { guid }).First();
                    error = null;
                }
                catch (Exception ex)
                {
                    error = ex.Message;
                }
                error.IsEqualTo("Error parsing column 0 (Id=cf0ef7ac-b6fe-4e24-aeda-a2b45bb5654e - Object)");
            }
            public class Issue149_Person { public string Id { get; set; } }
    
            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<string, object> {
                    { "myIds", new [] { 5, 6 } }
                };
    
                var dynamicParams = new DynamicParameters(queryParams);
                List<int> result = connection.Query<int>(query, dynamicParams).ToList();
                result.Count.IsEqualTo(2);
                result.Contains(5).IsTrue();
                result.Contains(6).IsTrue();
            }
    
            public void AllowIDictionaryParameters()
            {
                var parameters = new Dictionary<string, object>
                {
                    { "param1", 0 }
                };
    
                connection.Query("SELECT @param1", parameters);
            }
    
    
            public void Issue178_SqlServer()
            {
                const string sql = @"select count(*) from Issue178";
                try { connection.Execute("drop table Issue178"); }
                catch { }
                try { connection.Execute("create table Issue178(id int not null)"); }
                catch { }
                // raw ADO.net
                var sqlCmd = new SqlCommand(sql, connection);
                using (IDataReader reader1 = sqlCmd.ExecuteReader())
                {
                    Assert.IsTrue(reader1.Read());
                    reader1.GetInt32(0).IsEqualTo(0);
                    Assert.IsFalse(reader1.Read());
                    Assert.IsFalse(reader1.NextResult());
                }
    
                // dapper
                using (var reader2 = connection.ExecuteReader(sql))
                {
                    Assert.IsTrue(reader2.Read());
                    reader2.GetInt32(0).IsEqualTo(0);
                    Assert.IsFalse(reader2.Read());
                    Assert.IsFalse(reader2.NextResult());
                }
            }
    #if EXTERNALS
            public void Issue178_Firebird() // we expect this to fail due to a bug in Firebird; a PR to fix it has been submitted
            {
                var cs = @"initial catalog=localhost:database;user id=SYSDBA;password=masterkey";
    
                using (var connection = new FbConnection(cs))
                {
                    connection.Open();
                    const string sql = @"select count(*) from Issue178";
                    try { connection.Execute("drop table Issue178"); }
                    catch { }
                    connection.Execute("create table Issue178(id int not null)");
                    connection.Execute("insert into Issue178(id) values(42)");
                    // raw ADO.net
                    using (var sqlCmd = new FbCommand(sql, connection))
                    using (IDataReader reader1 = sqlCmd.ExecuteReader())
                    {
                        Assert.IsTrue(reader1.Read());
                        reader1.GetInt32(0).IsEqualTo(1);
                        Assert.IsFalse(reader1.Read());
                        Assert.IsFalse(reader1.NextResult());
                    }
    
                    // dapper
                    using (var reader2 = connection.ExecuteReader(sql))
                    {
                        Assert.IsTrue(reader2.Read());
                        reader2.GetInt32(0).IsEqualTo(1);
                        Assert.IsFalse(reader2.Read());
                        Assert.IsFalse(reader2.NextResult());
                    }
    
                    var count = connection.Query<int>(sql).Single();
                    count.IsEqualTo(1);
                }
            }
    
            public void PseudoPositionalParameters_Simple()
            {
                using (var connection = ConnectViaOledb())
                {
                    int value = connection.Query<int>("select ?x? + ?y_2? + ?z?", new { x = 1, y_2 = 3, z = 5, z2 = 24 }).Single();
                    value.IsEqualTo(9);
                }
            }
    
            public void PseudoPositionalParameters_Dynamic()
            {
                using (var connection = ConnectViaOledb())
                {
                    var args = new DynamicParameters();
                    args.Add("x", 1);
                    args.Add("y_2", 3);
                    args.Add("z", 5);
                    args.Add("z2", 24);
                    int value = connection.Query<int>("select ?x? + ?y_2? + ?z?", args).Single();
                    value.IsEqualTo(9);
                }
            }
    
            public void PseudoPositionalParameters_ReusedParameter()
            {
                using (var connection = ConnectViaOledb())
                {
                    try
                    {
                        int value = connection.Query<int>("select ?x? + ?y_2? + ?x?", new { x = 1, y_2 = 3 }).Single();
                        Assert.Fail();
                    }
                    catch (InvalidOperationException ex)
                    {
                        ex.Message.IsEqualTo("When passing parameters by position, each parameter can only be referenced once");
                    }
                }
            }
    
            public void PseudoPositionalParameters_ExecSingle()
            {
                using (var connection = ConnectViaOledb())
                {
                    var data = new { x = 6 };
                    connection.Execute("create table #named_single(val int not null)");
                    int count = connection.Execute("insert #named_single (val) values (?x?)", data);
                    int sum = (int)connection.ExecuteScalar("select sum(val) from #named_single");
                    count.IsEqualTo(1);
                    sum.IsEqualTo(6);
                }
            }
            public void PseudoPositionalParameters_ExecMulti()
            {
                using (var connection = ConnectViaOledb())
                {
                    var data = new[]
                    {
                        new { x = 1, y = 1 },
                        new { x = 3, y = 1 },
                        new { x = 6, y = 1 },
                    };
                    connection.Execute("create table #named_multi(val int not null)");
                    int count = connection.Execute("insert #named_multi (val) values (?x?)", data);
                    int sum = (int)connection.ExecuteScalar("select sum(val) from #named_multi");
                    count.IsEqualTo(3);
                    sum.IsEqualTo(10);
                }
            }
    #endif
            public void QueryBasicWithoutQuery()
            {
                int? i = connection.Query<int?>("print 'not a query'").FirstOrDefault();
                i.IsNull();
            }
    
            public void QueryComplexWithoutQuery()
            {
                var obj = connection.Query<Foo1>("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<Dyno>("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<int>("select * from (select 1 as Id) as X where Id in @ids", new { Ids = new[] { 1 } })
                          .IsSequenceEqualTo(new[] { 1 });
            }
    
            public void SO29343103_UtcDates()
            {
                const string sql = "select @date";
                var date = DateTime.UtcNow;
                var returned = connection.Query<DateTime>(sql, new { date }).Single();
                var delta = returned - date;
                Assert.IsTrue(delta.TotalMilliseconds >= -1 && delta.TotalMilliseconds <= 1);
            }
    #if DNXCORE50
            [FrameworkFail("https://github.com/dotnet/corefx/issues/1612")]
    #endif
            public void Issue261_Decimals()
            {
                var parameters = new DynamicParameters();
                parameters.Add("c", dbType: DbType.Decimal, direction: ParameterDirection.Output, precision: 10, scale: 5);
                connection.Execute("create proc #Issue261 @c decimal(10,5) OUTPUT as begin set @c=11.884 end");
                connection.Execute("#Issue261", parameters, commandType: CommandType.StoredProcedure);
                var c = parameters.Get<Decimal>("c");
                c.IsEqualTo(11.884M);
            }
    #if DNXCORE50
            [FrameworkFail("https://github.com/dotnet/corefx/issues/1612")]
    #endif
            public void Issue261_Decimals_ADONET_SetViaBaseClass()
            {
                Issue261_Decimals_ADONET(true);
            }
    
            public void Issue261_Decimals_ADONET_SetViaConcreteClass()
            {
                Issue261_Decimals_ADONET(false);
            }
            private void Issue261_Decimals_ADONET(bool setPrecisionScaleViaAbstractApi)
            {
                try
                {
                    using (var cmd = connection.CreateCommand())
                    {
                        cmd.CommandText = "create proc #Issue261Direct @c decimal(10,5) OUTPUT as begin set @c=11.884 end";
                        cmd.ExecuteNonQuery();
                    }
                }
                catch { /* we don't care that it already exists */ }
    
                using (var cmd = connection.CreateCommand())
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "#Issue261Direct";
                    var c = cmd.CreateParameter();
                    c.ParameterName = "c";
                    c.Direction = ParameterDirection.Output;
                    c.Value = DBNull.Value;
                    c.DbType = DbType.Decimal;
    
                    if (setPrecisionScaleViaAbstractApi)
                    {
    #if DNXCORE50
                        DbParameter baseParam = c;
    #else
                        IDbDataParameter baseParam = c;
    #endif
                        baseParam.Precision = 10;
                        baseParam.Scale = 5;
                    }
                    else
                    {
                        c.Precision = 10;
                        c.Scale = 5;
                    }
    
                    cmd.Parameters.Add(c);
                    cmd.ExecuteNonQuery();
                    decimal value = (decimal)c.Value;
                    value.IsEqualTo(11.884M);
                }
            }
    
            public void BasicDecimals()
            {
                var c = connection.Query<decimal>("select @c", new { c = 11.884M }).Single();
                c.IsEqualTo(11.884M);
            }
            [SkipTest]
            public void Issue263_Timeout()
            {
                var watch = Stopwatch.StartNew();
                var i = connection.Query<int>("waitfor delay '00:01:00'; select 42;", commandTimeout: 300, buffered: false).Single();
                watch.Stop();
                i.IsEqualTo(42);
                var minutes = watch.ElapsedMilliseconds / 1000 / 60;
                Assert.IsTrue(minutes >= 0.95 && minutes <= 1.05);
            }
    #if EXTERNALS
            public void SO29596645_TvpProperty()
            {
                try { connection.Execute("CREATE TYPE SO29596645_ReminderRuleType AS TABLE (id int NOT NULL)"); }
                catch { }
                connection.Execute(@"create proc #SO29596645_Proc (@Id int, @Rules SO29596645_ReminderRuleType READONLY)
                                    as begin select @Id + ISNULL((select sum(id) from @Rules), 0); end");
                var obj = new SO29596645_OrganisationDTO();
                int val = connection.Query<int>("#SO29596645_Proc", obj.Rules, commandType: CommandType.StoredProcedure).Single();
    
                // 4 + 9 + 7 = 20
                val.IsEqualTo(20);
    
            }
    #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<int>("RetVal");
                retVal.IsEqualTo(3);
            }
    #if EXTERNALS
            class SO29596645_RuleTableValuedParameters : Dapper.SqlMapper.IDynamicParameters {
                private string parameterName;
    
                public SO29596645_RuleTableValuedParameters(string parameterName)
                {
                    this.parameterName = parameterName;
                }
    
    
                public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
                {
                    Console.WriteLine("> AddParameters");
                    SqlCommand lazy = (SqlCommand)command;
                    lazy.Parameters.AddWithValue("Id", 7);
                    DataTable table = new DataTable {
                        Columns = {{"Id", typeof(int)}},
                        Rows = {{4}, {9}}
                    };
                    lazy.Parameters.AddWithValue("Rules", table);
                    Console.WriteLine("< AddParameters");
                }
            }
            class SO29596645_OrganisationDTO
            {
                public SO29596645_RuleTableValuedParameters Rules { get; private set; }
    
                public SO29596645_OrganisationDTO()
                {
                    Rules = new SO29596645_RuleTableValuedParameters("@Rules");
                }
            }
    #endif
    #if POSTGRESQL
    
            class Cat
            {
                public int Id { get; set; }
                public string Breed { get; set; }
                public string Name { get; set; }
            }
    
            Cat[] Cats = {
                                    new Cat() { Breed = "Abyssinian", Name="KACTUS"},
                                    new Cat() { Breed = "Aegean cat", Name="KADAFFI"},
                                    new Cat() { Breed = "American Bobtail", Name="KANJI"},
                                    new Cat() { Breed = "Balinese", Name="MACARONI"},
                                    new Cat() { Breed = "Bombay", Name="MACAULAY"},
                                    new Cat() { Breed = "Burmese", Name="MACBETH"},
                                    new Cat() { Breed = "Chartreux", Name="MACGYVER"},
                                    new Cat() { Breed = "German Rex", Name="MACKENZIE"},
                                    new Cat() { Breed = "Javanese", Name="MADISON"},
                                    new Cat() { Breed = "Persian", Name="MAGNA"}
                                };
    
            public void TestPostresqlArrayParameters()
            {
                using (var conn = new NpgsqlConnection("Server=localhost;Port=5432;User Id=dappertest;Password=dapperpass;Database=dappertest;Encoding=UNICODE"))
                {
                    conn.Open();
                    IDbTransaction transaction = conn.BeginTransaction();
                    conn.Execute("create table tcat ( id serial not null, breed character varying(20) not null, name character varying (20) not null);");
                    conn.Execute("insert into tcat(breed, name) values(:breed, :name) ", Cats);
    
                    var r = conn.Query<Cat>("select * from tcat where id=any(:catids)", new { catids = new[] { 1, 3, 5 } });
                    r.Count().IsEqualTo(3);
                    r.Count(c => c.Id == 1).IsEqualTo(1);
                    r.Count(c => c.Id == 3).IsEqualTo(1);
                    r.Count(c => c.Id == 5).IsEqualTo(1);
                    transaction.Rollback();
                }
            }
    #endif
    
            public void SO30156367_DynamicParamsWithoutExec()
            {
                var dbParams = new DynamicParameters();
                dbParams.Add("Field1", 1);
                var value = dbParams.Get<int>("Field1");
                value.IsEqualTo(1);
            }
    
            public void SO30435185_InvalidTypeOwner()
            {
                try {
                    string sql = @" INSERT INTO #XXX
                            (XXXId, AnotherId, ThirdId, Value, Comment)
                            VALUES
                            (@XXXId, @AnotherId, @ThirdId, @Value, @Comment); select @@rowcount as [Foo]";
    
                    var command = new
                    {
                        MyModels = new[]
                        {
                            new {XXXId = 1, AnotherId = 2, ThirdId = 3, Value = "abc", Comment = "def" }
                    }
                    };
                    var parameters = command
                        .MyModels
                        .Select(model => new
                        {
                            XXXId = model.XXXId,
                            AnotherId = model.AnotherId,
                            ThirdId = model.ThirdId,
                            Value = model.Value,
                            Comment = model.Comment
                        })
                        .ToArray();
    
                    var rowcount = (int)connection.Query(sql, parameters).Single().Foo;
                    rowcount.IsEqualTo(1);
    
                    Assert.Fail();
                } catch(InvalidOperationException ex)
                {
                    ex.Message.IsEqualTo("An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context");
                }
            }
        }
    }
    Status API Training Shop Blog About
    © 2015 GitHub, Inc. Terms Privacy Security Contact
  • 相关阅读:
    解决tomcat启东时一闪而过的问题
    如果数据库中的时间类型与mybatis的时间类型对应关系
    el 表达式中某一项过长时需要截取字符串长度,当悬停的时候显示全部内容
    ubuntu/linux系统中安装jdk以及eclipse(附图解详细步骤)
    Unity利用SMSSDK实现短信验证码(附代码)
    Unity利用Share SDK实现QQ、微信及微博第三方登录及定制内容分享(附代码)
    Unity编辑器扩展
    VR中射线点击按钮的实现
    Unity中几个特殊路径在各个平台的访问方式
    多态
  • 原文地址:https://www.cnblogs.com/starluck/p/4542363.html
Copyright © 2011-2022 走看看