PageRenderTime 70ms CodeModel.GetById 32ms RepoModel.GetById 9ms app.codeStats 0ms

/Tests/Tests.cs

https://github.com/jomit/dapper-dot-net
C# | 2315 lines | 1944 code | 328 blank | 43 comment | 14 complexity | 3afce8868624876fe516b0ea2def52c9 MD5 | raw file
  1. //#define POSTGRESQL // uncomment to run postgres tests
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Data.SqlClient;
  5. using System.Linq;
  6. using Dapper;
  7. using System.Data.SqlServerCe;
  8. using System.IO;
  9. using System.Data;
  10. using System.Collections;
  11. using System.Reflection;
  12. using System.Dynamic;
  13. using System.ComponentModel;
  14. using Microsoft.CSharp.RuntimeBinder;
  15. #if POSTGRESQL
  16. using Npgsql;
  17. #endif
  18. namespace SqlMapper
  19. {
  20. class Tests
  21. {
  22. SqlConnection connection = Program.GetOpenConnection();
  23. public class AbstractInheritance
  24. {
  25. public abstract class Order
  26. {
  27. internal int Internal { get; set; }
  28. protected int Protected { get; set; }
  29. public int Public { get; set; }
  30. public int ProtectedVal { get { return Protected; } }
  31. }
  32. public class ConcreteOrder : Order
  33. {
  34. public int Concrete { get; set; }
  35. }
  36. }
  37. class UserWithConstructor
  38. {
  39. public UserWithConstructor(int id, string name)
  40. {
  41. Ident = id;
  42. FullName = name;
  43. }
  44. public int Ident { get; set; }
  45. public string FullName { get; set; }
  46. }
  47. class PostWithConstructor
  48. {
  49. public PostWithConstructor(int id, int ownerid, string content)
  50. {
  51. Ident = id;
  52. FullContent = content;
  53. }
  54. public int Ident { get; set; }
  55. public UserWithConstructor Owner { get; set; }
  56. public string FullContent { get; set; }
  57. public Comment Comment { get; set; }
  58. }
  59. public void TestMultiMapWithConstructor()
  60. {
  61. var createSql = @"
  62. create table #Users (Id int, Name varchar(20))
  63. create table #Posts (Id int, OwnerId int, Content varchar(20))
  64. insert #Users values(99, 'Sam')
  65. insert #Users values(2, 'I am')
  66. insert #Posts values(1, 99, 'Sams Post1')
  67. insert #Posts values(2, 99, 'Sams Post2')
  68. insert #Posts values(3, null, 'no ones post')";
  69. connection.Execute(createSql);
  70. string sql = @"select * from #Posts p
  71. left join #Users u on u.Id = p.OwnerId
  72. Order by p.Id";
  73. PostWithConstructor[] data = connection.Query<PostWithConstructor, UserWithConstructor, PostWithConstructor>(sql, (post, user) => { post.Owner = user; return post;}).ToArray();
  74. var p = data.First();
  75. p.FullContent.IsEqualTo("Sams Post1");
  76. p.Ident.IsEqualTo(1);
  77. p.Owner.FullName.IsEqualTo("Sam");
  78. p.Owner.Ident.IsEqualTo(99);
  79. data[2].Owner.IsNull();
  80. connection.Execute("drop table #Users drop table #Posts");
  81. }
  82. class MultipleConstructors
  83. {
  84. public MultipleConstructors()
  85. {
  86. }
  87. public MultipleConstructors(int a, string b)
  88. {
  89. A = a + 1;
  90. B = b + "!";
  91. }
  92. public int A { get; set; }
  93. public string B { get; set; }
  94. }
  95. public void TestMultipleConstructors()
  96. {
  97. MultipleConstructors mult = connection.Query<MultipleConstructors>("select 0 A, 'Dapper' b").First();
  98. mult.A.IsEqualTo(0);
  99. mult.B.IsEqualTo("Dapper");
  100. }
  101. class ConstructorsWithAccessModifiers
  102. {
  103. private ConstructorsWithAccessModifiers()
  104. {
  105. }
  106. public ConstructorsWithAccessModifiers(int a, string b)
  107. {
  108. A = a + 1;
  109. B = b + "!";
  110. }
  111. public int A { get; set; }
  112. public string B { get; set; }
  113. }
  114. public void TestConstructorsWithAccessModifiers()
  115. {
  116. ConstructorsWithAccessModifiers value = connection.Query<ConstructorsWithAccessModifiers>("select 0 A, 'Dapper' b").First();
  117. value.A.IsEqualTo(1);
  118. value.B.IsEqualTo("Dapper!");
  119. }
  120. class NoDefaultConstructor
  121. {
  122. public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1)
  123. {
  124. A = a1;
  125. B = b1;
  126. F = f1;
  127. S = s1;
  128. G = G1;
  129. }
  130. public int A { get; set; }
  131. public int? B { get; set; }
  132. public float F { get; set; }
  133. public string S { get; set; }
  134. public Guid G { get; set; }
  135. }
  136. public void TestNoDefaultConstructor()
  137. {
  138. var guid = Guid.NewGuid();
  139. 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();
  140. nodef.A.IsEqualTo(0);
  141. nodef.B.IsEqualTo(null);
  142. nodef.F.IsEqualTo(0);
  143. nodef.S.IsEqualTo("Dapper");
  144. nodef.G.IsEqualTo(guid);
  145. }
  146. class NoDefaultConstructorWithChar
  147. {
  148. public NoDefaultConstructorWithChar(char c1, char? c2, char? c3)
  149. {
  150. Char1 = c1;
  151. Char2 = c2;
  152. Char3 = c3;
  153. }
  154. public char Char1 { get; set; }
  155. public char? Char2 { get; set; }
  156. public char? Char3 { get; set; }
  157. }
  158. public void TestNoDefaultConstructorWithChar()
  159. {
  160. const char c1 = 'ą';
  161. const char c3 = 'ó';
  162. NoDefaultConstructorWithChar nodef = connection.Query<NoDefaultConstructorWithChar>("select @c1 c1, @c2 c2, @c3 c3", new { c1 = c1, c2 = (char?)null, c3 = c3 }).First();
  163. nodef.Char1.IsEqualTo(c1);
  164. nodef.Char2.IsEqualTo(null);
  165. nodef.Char3.IsEqualTo(c3);
  166. }
  167. class NoDefaultConstructorWithEnum
  168. {
  169. public NoDefaultConstructorWithEnum(ShortEnum e1, ShortEnum? n1, ShortEnum? n2)
  170. {
  171. E = e1;
  172. NE1 = n1;
  173. NE2 = n2;
  174. }
  175. public ShortEnum E { get; set; }
  176. public ShortEnum? NE1 { get; set; }
  177. public ShortEnum? NE2 { get; set; }
  178. }
  179. public void TestNoDefaultConstructorWithEnum()
  180. {
  181. NoDefaultConstructorWithEnum nodef = connection.Query<NoDefaultConstructorWithEnum>("select cast(2 as smallint) E1, cast(5 as smallint) n1, cast(null as smallint) n2").First();
  182. nodef.E.IsEqualTo(ShortEnum.Two);
  183. nodef.NE1.IsEqualTo(ShortEnum.Five);
  184. nodef.NE2.IsEqualTo(null);
  185. }
  186. class NoDefaultConstructorWithBinary
  187. {
  188. public System.Data.Linq.Binary Value { get; set; }
  189. public int Ynt { get; set; }
  190. public NoDefaultConstructorWithBinary(System.Data.Linq.Binary val)
  191. {
  192. Value = val;
  193. }
  194. }
  195. public void TestNoDefaultConstructorBinary()
  196. {
  197. byte[] orig = new byte[20];
  198. new Random(123456).NextBytes(orig);
  199. var input = new System.Data.Linq.Binary(orig);
  200. var output = connection.Query<NoDefaultConstructorWithBinary>("select @input as val", new { input }).First().Value;
  201. output.ToArray().IsSequenceEqualTo(orig);
  202. }
  203. // http://stackoverflow.com/q/8593871
  204. public void TestAbstractInheritance()
  205. {
  206. var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();
  207. order.Internal.IsEqualTo(1);
  208. order.ProtectedVal.IsEqualTo(2);
  209. order.Public.IsEqualTo(3);
  210. order.Concrete.IsEqualTo(4);
  211. }
  212. public void TestListOfAnsiStrings()
  213. {
  214. var results = connection.Query<string>("select * from (select 'a' str union select 'b' union select 'c') X where str in @strings",
  215. new { strings = new[] { new DbString { IsAnsi = true, Value = "a" }, new DbString { IsAnsi = true, Value = "b" } } }).ToList();
  216. results[0].IsEqualTo("a");
  217. results[1].IsEqualTo("b");
  218. }
  219. public void TestNullableGuidSupport()
  220. {
  221. var guid = connection.Query<Guid?>("select null").First();
  222. guid.IsNull();
  223. guid = Guid.NewGuid();
  224. var guid2 = connection.Query<Guid?>("select @guid", new { guid }).First();
  225. guid.IsEqualTo(guid2);
  226. }
  227. public void TestNonNullableGuidSupport()
  228. {
  229. var guid = Guid.NewGuid();
  230. var guid2 = connection.Query<Guid?>("select @guid", new { guid }).First();
  231. Assert.IsTrue(guid == guid2);
  232. }
  233. struct Car
  234. {
  235. public enum TrapEnum : int
  236. {
  237. A = 1,
  238. B = 2
  239. }
  240. #pragma warning disable 0649
  241. public string Name;
  242. #pragma warning restore 0649
  243. public int Age { get; set; }
  244. public TrapEnum Trap { get; set; }
  245. }
  246. public void TestStructs()
  247. {
  248. var car = connection.Query<Car>("select 'Ford' Name, 21 Age, 2 Trap").First();
  249. car.Age.IsEqualTo(21);
  250. car.Name.IsEqualTo("Ford");
  251. ((int)car.Trap).IsEqualTo(2);
  252. }
  253. public void SelectListInt()
  254. {
  255. connection.Query<int>("select 1 union all select 2 union all select 3")
  256. .IsSequenceEqualTo(new[] { 1, 2, 3 });
  257. }
  258. public void SelectBinary()
  259. {
  260. connection.Query<byte[]>("select cast(1 as varbinary(4))").First().SequenceEqual(new byte[] { 1 });
  261. }
  262. public void PassInIntArray()
  263. {
  264. 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() })
  265. .IsSequenceEqualTo(new[] { 1, 2, 3 });
  266. }
  267. public void PassInEmptyIntArray()
  268. {
  269. 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] })
  270. .IsSequenceEqualTo(new int[0]);
  271. }
  272. public void TestSchemaChanged()
  273. {
  274. connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
  275. var d = connection.Query<Dog>("select * from #dog").Single();
  276. d.Name.IsEqualTo("Alf");
  277. d.Age.IsEqualTo(1);
  278. connection.Execute("alter table #dog drop column Name");
  279. d = connection.Query<Dog>("select * from #dog").Single();
  280. d.Name.IsNull();
  281. d.Age.IsEqualTo(1);
  282. connection.Execute("drop table #dog");
  283. }
  284. public void TestSchemaChangedMultiMap()
  285. {
  286. connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
  287. 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();
  288. tuple.Item1.Name.IsEqualTo("Alf");
  289. tuple.Item1.Age.IsEqualTo(1);
  290. tuple.Item2.Name.IsEqualTo("Alf");
  291. tuple.Item2.Age.IsEqualTo(1);
  292. connection.Execute("alter table #dog drop column Name");
  293. 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();
  294. tuple.Item1.Name.IsNull();
  295. tuple.Item1.Age.IsEqualTo(1);
  296. tuple.Item2.Name.IsNull();
  297. tuple.Item2.Age.IsEqualTo(1);
  298. connection.Execute("drop table #dog");
  299. }
  300. public void TestReadMultipleIntegersWithSplitOnAny()
  301. {
  302. connection.Query<int, int, int, Tuple<int, int, int>>(
  303. "select 1,2,3 union all select 4,5,6", Tuple.Create, splitOn: "*")
  304. .IsSequenceEqualTo(new[] { Tuple.Create(1, 2, 3), Tuple.Create(4, 5, 6) });
  305. }
  306. public void TestDoubleParam()
  307. {
  308. connection.Query<double>("select @d", new { d = 0.1d }).First()
  309. .IsEqualTo(0.1d);
  310. }
  311. public void TestBoolParam()
  312. {
  313. connection.Query<bool>("select @b", new { b = false }).First()
  314. .IsFalse();
  315. }
  316. // http://code.google.com/p/dapper-dot-net/issues/detail?id=70
  317. // https://connect.microsoft.com/VisualStudio/feedback/details/381934/sqlparameter-dbtype-dbtype-time-sets-the-parameter-to-sqldbtype-datetime-instead-of-sqldbtype-time
  318. public void TestTimeSpanParam()
  319. {
  320. connection.Query<TimeSpan>("select @ts", new { ts = TimeSpan.FromMinutes(42) }).First()
  321. .IsEqualTo(TimeSpan.FromMinutes(42));
  322. }
  323. public void TestStrings()
  324. {
  325. connection.Query<string>(@"select 'a' a union select 'b'")
  326. .IsSequenceEqualTo(new[] { "a", "b" });
  327. }
  328. enum EnumParam : short
  329. {
  330. None, A, B
  331. }
  332. class EnumParamObject
  333. {
  334. public EnumParam A { get; set; }
  335. public EnumParam? B { get; set; }
  336. public EnumParam? C { get; set; }
  337. }
  338. class EnumParamObjectNonNullable
  339. {
  340. public EnumParam A { get; set; }
  341. public EnumParam? B { get; set; }
  342. public EnumParam? C { get; set; }
  343. }
  344. public void TestEnumParamsWithNullable()
  345. {
  346. EnumParam a = EnumParam.A;
  347. EnumParam? b = EnumParam.B, c = null;
  348. var obj = connection.Query<EnumParamObject>("select @a as A, @b as B, @c as C",
  349. new { a, b, c }).Single();
  350. obj.A.IsEqualTo(EnumParam.A);
  351. obj.B.IsEqualTo(EnumParam.B);
  352. obj.C.IsEqualTo(null);
  353. }
  354. public void TestEnumParamsWithoutNullable()
  355. {
  356. EnumParam a = EnumParam.A;
  357. EnumParam b = EnumParam.B, c = 0;
  358. var obj = connection.Query<EnumParamObjectNonNullable>("select @a as A, @b as B, @c as C",
  359. new { a, b, c }).Single();
  360. obj.A.IsEqualTo(EnumParam.A);
  361. obj.B.IsEqualTo(EnumParam.B);
  362. obj.C.IsEqualTo((EnumParam)0);
  363. }
  364. public class Dog
  365. {
  366. public int? Age { get; set; }
  367. public Guid Id { get; set; }
  368. public string Name { get; set; }
  369. public float? Weight { get; set; }
  370. public int IgnoredProperty { get { return 1; } }
  371. }
  372. public void TestExtraFields()
  373. {
  374. var guid = Guid.NewGuid();
  375. var dog = connection.Query<Dog>("select '' as Extra, 1 as Age, 0.1 as Name1 , Id = @id", new { Id = guid });
  376. dog.Count()
  377. .IsEqualTo(1);
  378. dog.First().Age
  379. .IsEqualTo(1);
  380. dog.First().Id
  381. .IsEqualTo(guid);
  382. }
  383. public void TestStrongType()
  384. {
  385. var guid = Guid.NewGuid();
  386. var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
  387. dog.Count()
  388. .IsEqualTo(1);
  389. dog.First().Age
  390. .IsNull();
  391. dog.First().Id
  392. .IsEqualTo(guid);
  393. }
  394. public void TestSimpleNull()
  395. {
  396. connection.Query<DateTime?>("select null").First().IsNull();
  397. }
  398. public void TestExpando()
  399. {
  400. var rows = connection.Query("select 1 A, 2 B union all select 3, 4").ToList();
  401. ((int)rows[0].A)
  402. .IsEqualTo(1);
  403. ((int)rows[0].B)
  404. .IsEqualTo(2);
  405. ((int)rows[1].A)
  406. .IsEqualTo(3);
  407. ((int)rows[1].B)
  408. .IsEqualTo(4);
  409. }
  410. public void TestStringList()
  411. {
  412. 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" } })
  413. .IsSequenceEqualTo(new[] { "a", "b", "c" });
  414. 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] })
  415. .IsSequenceEqualTo(new string[0]);
  416. }
  417. public void TestExecuteCommand()
  418. {
  419. connection.Execute(@"
  420. set nocount on
  421. create table #t(i int)
  422. set nocount off
  423. insert #t
  424. select @a a union all select @b
  425. set nocount on
  426. drop table #t", new { a = 1, b = 2 }).IsEqualTo(2);
  427. }
  428. public void TestExecuteCommandWithHybridParameters()
  429. {
  430. var p = new DynamicParameters(new { a = 1, b = 2 });
  431. p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.Output);
  432. connection.Execute(@"set @c = @a + @b", p);
  433. p.Get<int>("@c").IsEqualTo(3);
  434. }
  435. public void TestExecuteMultipleCommand()
  436. {
  437. connection.Execute("create table #t(i int)");
  438. int tally = connection.Execute(@"insert #t (i) values(@a)", new[] { new { a = 1 }, new { a = 2 }, new { a = 3 }, new { a = 4 } });
  439. int sum = connection.Query<int>("select sum(i) from #t drop table #t").First();
  440. tally.IsEqualTo(4);
  441. sum.IsEqualTo(10);
  442. }
  443. class Student
  444. {
  445. public string Name { get; set; }
  446. public int Age { get; set; }
  447. }
  448. public void TestExecuteMultipleCommandStrongType()
  449. {
  450. connection.Execute("create table #t(Name nvarchar(max), Age int)");
  451. int tally = connection.Execute(@"insert #t (Name,Age) values(@Name, @Age)", new List<Student>
  452. {
  453. new Student{Age = 1, Name = "sam"},
  454. new Student{Age = 2, Name = "bob"}
  455. });
  456. int sum = connection.Query<int>("select sum(Age) from #t drop table #t").First();
  457. tally.IsEqualTo(2);
  458. sum.IsEqualTo(3);
  459. }
  460. public void TestExecuteMultipleCommandObjectArray()
  461. {
  462. connection.Execute("create table #t(i int)");
  463. int tally = connection.Execute(@"insert #t (i) values(@a)", new object[] { new { a = 1 }, new { a = 2 }, new { a = 3 }, new { a = 4 } });
  464. int sum = connection.Query<int>("select sum(i) from #t drop table #t").First();
  465. tally.IsEqualTo(4);
  466. sum.IsEqualTo(10);
  467. }
  468. public void TestMassiveStrings()
  469. {
  470. var str = new string('X', 20000);
  471. connection.Query<string>("select @a", new { a = str }).First()
  472. .IsEqualTo(str);
  473. }
  474. class TestObj
  475. {
  476. public int _internal;
  477. internal int Internal { set { _internal = value; } }
  478. public int _priv;
  479. private int Priv { set { _priv = value; } }
  480. }
  481. public void TestSetInternal()
  482. {
  483. connection.Query<TestObj>("select 10 as [Internal]").First()._internal.IsEqualTo(10);
  484. }
  485. public void TestSetPrivate()
  486. {
  487. connection.Query<TestObj>("select 10 as [Priv]").First()._priv.IsEqualTo(10);
  488. }
  489. public void TestEnumeration()
  490. {
  491. var en = connection.Query<int>("select 1 as one union all select 2 as one", buffered: false);
  492. var i = en.GetEnumerator();
  493. i.MoveNext();
  494. bool gotException = false;
  495. try
  496. {
  497. var x = connection.Query<int>("select 1 as one", buffered: false).First();
  498. }
  499. catch (Exception)
  500. {
  501. gotException = true;
  502. }
  503. while (i.MoveNext())
  504. { }
  505. // should not exception, since enumertated
  506. en = connection.Query<int>("select 1 as one", buffered: false);
  507. gotException.IsTrue();
  508. }
  509. public void TestEnumerationDynamic()
  510. {
  511. var en = connection.Query("select 1 as one union all select 2 as one", buffered: false);
  512. var i = en.GetEnumerator();
  513. i.MoveNext();
  514. bool gotException = false;
  515. try
  516. {
  517. var x = connection.Query("select 1 as one", buffered: false).First();
  518. }
  519. catch (Exception)
  520. {
  521. gotException = true;
  522. }
  523. while (i.MoveNext())
  524. { }
  525. // should not exception, since enumertated
  526. en = connection.Query("select 1 as one", buffered: false);
  527. gotException.IsTrue();
  528. }
  529. public void TestNakedBigInt()
  530. {
  531. long foo = 12345;
  532. var result = connection.Query<long>("select @foo", new { foo }).Single();
  533. foo.IsEqualTo(result);
  534. }
  535. public void TestBigIntMember()
  536. {
  537. long foo = 12345;
  538. var result = connection.Query<WithBigInt>(@"
  539. declare @bar table(Value bigint)
  540. insert @bar values (@foo)
  541. select * from @bar", new { foo }).Single();
  542. result.Value.IsEqualTo(foo);
  543. }
  544. class WithBigInt
  545. {
  546. public long Value { get; set; }
  547. }
  548. class User
  549. {
  550. public int Id { get; set; }
  551. public string Name { get; set; }
  552. }
  553. class Post
  554. {
  555. public int Id { get; set; }
  556. public User Owner { get; set; }
  557. public string Content { get; set; }
  558. public Comment Comment { get; set; }
  559. }
  560. public void TestMultiMap()
  561. {
  562. var createSql = @"
  563. create table #Users (Id int, Name varchar(20))
  564. create table #Posts (Id int, OwnerId int, Content varchar(20))
  565. insert #Users values(99, 'Sam')
  566. insert #Users values(2, 'I am')
  567. insert #Posts values(1, 99, 'Sams Post1')
  568. insert #Posts values(2, 99, 'Sams Post2')
  569. insert #Posts values(3, null, 'no ones post')
  570. ";
  571. connection.Execute(createSql);
  572. var sql =
  573. @"select * from #Posts p
  574. left join #Users u on u.Id = p.OwnerId
  575. Order by p.Id";
  576. var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }).ToList();
  577. var p = data.First();
  578. p.Content.IsEqualTo("Sams Post1");
  579. p.Id.IsEqualTo(1);
  580. p.Owner.Name.IsEqualTo("Sam");
  581. p.Owner.Id.IsEqualTo(99);
  582. data[2].Owner.IsNull();
  583. connection.Execute("drop table #Users drop table #Posts");
  584. }
  585. public void TestMultiMapGridReader()
  586. {
  587. var createSql = @"
  588. create table #Users (Id int, Name varchar(20))
  589. create table #Posts (Id int, OwnerId int, Content varchar(20))
  590. insert #Users values(99, 'Sam')
  591. insert #Users values(2, 'I am')
  592. insert #Posts values(1, 99, 'Sams Post1')
  593. insert #Posts values(2, 99, 'Sams Post2')
  594. insert #Posts values(3, null, 'no ones post')
  595. ";
  596. connection.Execute(createSql);
  597. var sql =
  598. @"select p.*, u.Id, u.Name + '0' Name from #Posts p
  599. left join #Users u on u.Id = p.OwnerId
  600. Order by p.Id
  601. select p.*, u.Id, u.Name + '1' Name from #Posts p
  602. left join #Users u on u.Id = p.OwnerId
  603. Order by p.Id
  604. ";
  605. var grid = connection.QueryMultiple(sql);
  606. for (int i = 0; i < 2; i++)
  607. {
  608. var data = grid.Read<Post, User, Post>((post, user) => { post.Owner = user; return post; }).ToList();
  609. var p = data.First();
  610. p.Content.IsEqualTo("Sams Post1");
  611. p.Id.IsEqualTo(1);
  612. p.Owner.Name.IsEqualTo("Sam" + i);
  613. p.Owner.Id.IsEqualTo(99);
  614. data[2].Owner.IsNull();
  615. }
  616. connection.Execute("drop table #Users drop table #Posts");
  617. }
  618. public void TestQueryMultipleBuffered()
  619. {
  620. using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
  621. {
  622. var a = grid.Read<int>();
  623. var b = grid.Read<int>();
  624. var c = grid.Read<int>();
  625. var d = grid.Read<int>();
  626. a.Single().Equals(1);
  627. b.Single().Equals(2);
  628. c.Single().Equals(3);
  629. d.Single().Equals(4);
  630. }
  631. }
  632. public void TestQueryMultipleNonBufferedIncorrectOrder()
  633. {
  634. using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
  635. {
  636. var a = grid.Read<int>(false);
  637. try
  638. {
  639. var b = grid.Read<int>(false);
  640. throw new InvalidOperationException(); // should have thrown
  641. }
  642. catch (InvalidOperationException)
  643. {
  644. // that's expected
  645. }
  646. }
  647. }
  648. public void TestQueryMultipleNonBufferedCcorrectOrder()
  649. {
  650. using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
  651. {
  652. var a = grid.Read<int>(false).Single();
  653. var b = grid.Read<int>(false).Single();
  654. var c = grid.Read<int>(false).Single();
  655. var d = grid.Read<int>(false).Single();
  656. a.Equals(1);
  657. b.Equals(2);
  658. c.Equals(3);
  659. d.Equals(4);
  660. }
  661. }
  662. public void TestMultiMapDynamic()
  663. {
  664. var createSql = @"
  665. create table #Users (Id int, Name varchar(20))
  666. create table #Posts (Id int, OwnerId int, Content varchar(20))
  667. insert #Users values(99, 'Sam')
  668. insert #Users values(2, 'I am')
  669. insert #Posts values(1, 99, 'Sams Post1')
  670. insert #Posts values(2, 99, 'Sams Post2')
  671. insert #Posts values(3, null, 'no ones post')
  672. ";
  673. connection.Execute(createSql);
  674. var sql =
  675. @"select * from #Posts p
  676. left join #Users u on u.Id = p.OwnerId
  677. Order by p.Id";
  678. var data = connection.Query<dynamic, dynamic, dynamic>(sql, (post, user) => { post.Owner = user; return post; }).ToList();
  679. var p = data.First();
  680. // hairy extension method support for dynamics
  681. ((string)p.Content).IsEqualTo("Sams Post1");
  682. ((int)p.Id).IsEqualTo(1);
  683. ((string)p.Owner.Name).IsEqualTo("Sam");
  684. ((int)p.Owner.Id).IsEqualTo(99);
  685. ((object)data[2].Owner).IsNull();
  686. connection.Execute("drop table #Users drop table #Posts");
  687. }
  688. class Product
  689. {
  690. public int Id { get; set; }
  691. public string Name { get; set; }
  692. public Category Category { get; set; }
  693. }
  694. class Category
  695. {
  696. public int Id { get; set; }
  697. public string Name { get; set; }
  698. public string Description { get; set; }
  699. }
  700. public void TestMultiMapWithSplit() // http://stackoverflow.com/q/6056778/23354
  701. {
  702. var sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name";
  703. var product = connection.Query<Product, Category, Product>(sql, (prod, cat) =>
  704. {
  705. prod.Category = cat;
  706. return prod;
  707. }).First();
  708. // assertions
  709. product.Id.IsEqualTo(1);
  710. product.Name.IsEqualTo("abc");
  711. product.Category.Id.IsEqualTo(2);
  712. product.Category.Name.IsEqualTo("def");
  713. }
  714. public void TestMultiMapWithSplitWithNullValue() // http://stackoverflow.com/q/10744728/449906
  715. {
  716. var sql = @"select 1 as id, 'abc' as name, NULL as description, 'def' as name";
  717. var product = connection.Query<Product, Category, Product>(sql, (prod, cat) =>
  718. {
  719. prod.Category = cat;
  720. return prod;
  721. }, splitOn: "description").First();
  722. // assertions
  723. product.Id.IsEqualTo(1);
  724. product.Name.IsEqualTo("abc");
  725. product.Category.IsNull();
  726. }
  727. public void TestMultiMapWithSplitWithNullValueAndSpoofColumn() // http://stackoverflow.com/q/10744728/449906
  728. {
  729. var sql = @"select 1 as id, 'abc' as name, 1 as spoof, NULL as description, 'def' as name";
  730. var product = connection.Query<Product, Category, Product>(sql, (prod, cat) =>
  731. {
  732. prod.Category = cat;
  733. return prod;
  734. }, splitOn: "spoof").First();
  735. // assertions
  736. product.Id.IsEqualTo(1);
  737. product.Name.IsEqualTo("abc");
  738. product.Category.IsNotNull();
  739. product.Category.Id.IsEqualTo(0);
  740. product.Category.Name.IsEqualTo("def");
  741. product.Category.Description.IsNull();
  742. }
  743. public void TestFieldsAndPrivates()
  744. {
  745. var data = connection.Query<TestFieldCaseAndPrivatesEntity>(
  746. @"select a=1,b=2,c=3,d=4,f='5'").Single();
  747. data.a.IsEqualTo(1);
  748. data.GetB().IsEqualTo(2);
  749. data.c.IsEqualTo(3);
  750. data.GetD().IsEqualTo(4);
  751. data.e.IsEqualTo(5);
  752. }
  753. private class TestFieldCaseAndPrivatesEntity
  754. {
  755. public int a { get; set; }
  756. private int b { get; set; }
  757. public int GetB() { return b; }
  758. public int c = 0;
  759. private int d = 0;
  760. public int GetD() { return d; }
  761. public int e { get; set; }
  762. private string f
  763. {
  764. get { return e.ToString(); }
  765. set { e = int.Parse(value); }
  766. }
  767. }
  768. public void TestMultiReaderBasic()
  769. {
  770. 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";
  771. int i, j;
  772. string s;
  773. using (var multi = connection.QueryMultiple(sql))
  774. {
  775. i = multi.Read<int>().First();
  776. s = multi.Read<string>().Single();
  777. j = multi.Read<int>().Sum();
  778. }
  779. Assert.IsEqualTo(i, 1);
  780. Assert.IsEqualTo(s, "abc");
  781. Assert.IsEqualTo(j, 3);
  782. }
  783. public void TestMultiMappingVariations()
  784. {
  785. 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";
  786. var order = connection.Query<dynamic, dynamic, dynamic, dynamic>(sql, (o, owner, creator) => { o.Owner = owner; o.Creator = creator; return o; }).First();
  787. Assert.IsEqualTo(order.Id, 1);
  788. Assert.IsEqualTo(order.Content, "a");
  789. Assert.IsEqualTo(order.Owner.Id, 2);
  790. Assert.IsEqualTo(order.Owner.Content, "b");
  791. Assert.IsEqualTo(order.Creator.Id, 3);
  792. Assert.IsEqualTo(order.Creator.Content, "c");
  793. order = connection.Query<dynamic, dynamic, dynamic, dynamic, dynamic>(sql, (o, owner, creator, address) =>
  794. {
  795. o.Owner = owner;
  796. o.Creator = creator;
  797. o.Owner.Address = address;
  798. return o;
  799. }).First();
  800. Assert.IsEqualTo(order.Id, 1);
  801. Assert.IsEqualTo(order.Content, "a");
  802. Assert.IsEqualTo(order.Owner.Id, 2);
  803. Assert.IsEqualTo(order.Owner.Content, "b");
  804. Assert.IsEqualTo(order.Creator.Id, 3);
  805. Assert.IsEqualTo(order.Creator.Content, "c");
  806. Assert.IsEqualTo(order.Owner.Address.Id, 4);
  807. Assert.IsEqualTo(order.Owner.Address.Content, "d");
  808. 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();
  809. Assert.IsEqualTo(order.Id, 1);
  810. Assert.IsEqualTo(order.Content, "a");
  811. Assert.IsEqualTo(order.B.Id, 2);
  812. Assert.IsEqualTo(order.B.Content, "b");
  813. Assert.IsEqualTo(order.C.Id, 3);
  814. Assert.IsEqualTo(order.C.Content, "c");
  815. Assert.IsEqualTo(order.C.D.Id, 4);
  816. Assert.IsEqualTo(order.C.D.Content, "d");
  817. Assert.IsEqualTo(order.E.Id, 5);
  818. Assert.IsEqualTo(order.E.Content, "e");
  819. }
  820. class InheritanceTest1
  821. {
  822. public string Base1 { get; set; }
  823. public string Base2 { get; private set; }
  824. }
  825. class InheritanceTest2 : InheritanceTest1
  826. {
  827. public string Derived1 { get; set; }
  828. public string Derived2 { get; private set; }
  829. }
  830. public void TestInheritance()
  831. {
  832. // Test that inheritance works.
  833. var list = connection.Query<InheritanceTest2>("select 'One' as Derived1, 'Two' as Derived2, 'Three' as Base1, 'Four' as Base2");
  834. list.First().Derived1.IsEqualTo("One");
  835. list.First().Derived2.IsEqualTo("Two");
  836. list.First().Base1.IsEqualTo("Three");
  837. list.First().Base2.IsEqualTo("Four");
  838. }
  839. public class PostCE
  840. {
  841. public int ID { get; set; }
  842. public string Title { get; set; }
  843. public string Body { get; set; }
  844. public AuthorCE Author { get; set; }
  845. }
  846. public class AuthorCE
  847. {
  848. public int ID { get; set; }
  849. public string Name { get; set; }
  850. }
  851. public void MultiRSSqlCE()
  852. {
  853. if (File.Exists("Test.sdf"))
  854. File.Delete("Test.sdf");
  855. var cnnStr = "Data Source = Test.sdf;";
  856. var engine = new SqlCeEngine(cnnStr);
  857. engine.CreateDatabase();
  858. using (var cnn = new SqlCeConnection(cnnStr))
  859. {
  860. cnn.Open();
  861. cnn.Execute("create table Posts (ID int, Title nvarchar(50), Body nvarchar(50), AuthorID int)");
  862. cnn.Execute("create table Authors (ID int, Name nvarchar(50))");
  863. cnn.Execute("insert Posts values (1,'title','body',1)");
  864. cnn.Execute("insert Posts values(2,'title2','body2',null)");
  865. cnn.Execute("insert Authors values(1,'sam')");
  866. 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();
  867. var firstPost = data.First();
  868. firstPost.Title.IsEqualTo("title");
  869. firstPost.Author.Name.IsEqualTo("sam");
  870. data[1].Author.IsNull();
  871. cnn.Close();
  872. }
  873. }
  874. enum TestEnum : byte
  875. {
  876. Bla = 1
  877. }
  878. class TestEnumClass
  879. {
  880. public TestEnum? EnumEnum { get; set; }
  881. }
  882. class TestEnumClassNoNull
  883. {
  884. public TestEnum EnumEnum { get; set; }
  885. }
  886. public void TestEnumWeirdness()
  887. {
  888. connection.Query<TestEnumClass>("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null);
  889. connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
  890. }
  891. public void TestEnumStrings()
  892. {
  893. connection.Query<TestEnumClassNoNull>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
  894. connection.Query<TestEnumClassNoNull>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
  895. connection.Query<TestEnumClass>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
  896. connection.Query<TestEnumClass>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
  897. }
  898. public void TestSupportForDynamicParameters()
  899. {
  900. var p = new DynamicParameters();
  901. p.Add("name", "bob");
  902. p.Add("age", dbType: DbType.Int32, direction: ParameterDirection.Output);
  903. connection.Query<string>("set @age = 11 select @name", p).First().IsEqualTo("bob");
  904. p.Get<int>("age").IsEqualTo(11);
  905. }
  906. public void TestSupportForExpandoObjectParameters()
  907. {
  908. dynamic p = new ExpandoObject();
  909. p.name = "bob";
  910. object parameters = p;
  911. string result = connection.Query<string>("select @name", parameters).First();
  912. result.IsEqualTo("bob");
  913. }
  914. public void TestProcSupport()
  915. {
  916. var p = new DynamicParameters();
  917. p.Add("a", 11);
  918. p.Add("b", dbType: DbType.Int32, direction: ParameterDirection.Output);
  919. p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
  920. connection.Execute(@"create proc #TestProc
  921. @a int,
  922. @b int output
  923. as
  924. begin
  925. set @b = 999
  926. select 1111
  927. return @a
  928. end");
  929. connection.Query<int>("#TestProc", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(1111);
  930. p.Get<int>("c").IsEqualTo(11);
  931. p.Get<int>("b").IsEqualTo(999);
  932. }
  933. public void TestDbString()
  934. {
  935. 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",
  936. new
  937. {
  938. a = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true },
  939. b = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = false },
  940. c = new DbString { Value = "abcde", IsFixedLength = false, Length = 10, IsAnsi = true },
  941. d = new DbString { Value = "abcde", IsFixedLength = false, Length = 10, IsAnsi = false },
  942. e = new DbString { Value = "abcde", IsAnsi = true },
  943. f = new DbString { Value = "abcde", IsAnsi = false },
  944. }).First();
  945. ((int)obj.a).IsEqualTo(10);
  946. ((int)obj.b).IsEqualTo(20);
  947. ((int)obj.c).IsEqualTo(5);
  948. ((int)obj.d).IsEqualTo(10);
  949. ((int)obj.e).IsEqualTo(5);
  950. ((int)obj.f).IsEqualTo(10);
  951. }
  952. class Person
  953. {
  954. public int PersonId { get; set; }
  955. public string Name { get; set; }
  956. }
  957. class Address
  958. {
  959. public int AddressId { get; set; }
  960. public string Name { get; set; }
  961. public int PersonId { get; set; }
  962. }
  963. class Extra
  964. {
  965. public int Id { get; set; }
  966. public string Name { get; set; }
  967. }
  968. public void TestFlexibleMultiMapping()
  969. {
  970. var sql =
  971. @"select
  972. 1 as PersonId, 'bob' as Name,
  973. 2 as AddressId, 'abc street' as Name, 1 as PersonId,
  974. 3 as Id, 'fred' as Name
  975. ";
  976. var personWithAddress = connection.Query<Person, Address, Extra, Tuple<Person, Address, Extra>>
  977. (sql, (p, a, e) => Tuple.Create(p, a, e), splitOn: "AddressId,Id").First();
  978. personWithAddress.Item1.PersonId.IsEqualTo(1);
  979. personWithAddress.Item1.Name.IsEqualTo("bob");
  980. personWithAddress.Item2.AddressId.IsEqualTo(2);
  981. personWithAddress.Item2.Name.IsEqualTo("abc street");
  982. personWithAddress.Item2.PersonId.IsEqualTo(1);
  983. personWithAddress.Item3.Id.IsEqualTo(3);
  984. personWithAddress.Item3.Name.IsEqualTo("fred");
  985. }
  986. public void TestMultiMappingWithSplitOnSpaceBetweenCommas()
  987. {
  988. var sql = @"select
  989. 1 as PersonId, 'bob' as Name,
  990. 2 as AddressId, 'abc street' as Name, 1 as PersonId,
  991. 3 as Id, 'fred' as Name
  992. ";
  993. var personWithAddress = connection.Query<Person, Address, Extra, Tuple<Person, Address, Extra>>
  994. (sql, (p, a, e) => Tuple.Create(p, a, e), splitOn: "AddressId, Id").First();
  995. personWithAddress.Item1.PersonId.IsEqualTo(1);
  996. personWithAddress.Item1.Name.IsEqualTo("bob");
  997. personWithAddress.Item2.AddressId.IsEqualTo(2);
  998. personWithAddress.Item2.Name.IsEqualTo("abc street");
  999. personWithAddress.Item2.PersonId.IsEqualTo(1);
  1000. personWithAddress.Item3.Id.IsEqualTo(3);
  1001. personWithAddress.Item3.Name.IsEqualTo("fred");
  1002. }
  1003. public void TestFastExpandoSupportsIDictionary()
  1004. {
  1005. var row = connection.Query("select 1 A, 'two' B").First() as IDictionary<string, object>;
  1006. row["A"].IsEqualTo(1);
  1007. row["B"].IsEqualTo("two");
  1008. }
  1009. class PrivateDan
  1010. {
  1011. public int Shadow { get; set; }
  1012. private string ShadowInDB
  1013. {
  1014. set
  1015. {
  1016. Shadow = value == "one" ? 1 : 0;
  1017. }
  1018. }
  1019. }
  1020. public void TestDapperSetsPrivates()
  1021. {
  1022. connection.Query<PrivateDan>("select 'one' ShadowInDB").First().Shadow.IsEqualTo(1);
  1023. }
  1024. class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters
  1025. {
  1026. IEnumerable<int> numbers;
  1027. public IntDynamicParam(IEnumerable<int> numbers)
  1028. {
  1029. this.numbers = numbers;
  1030. }
  1031. public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
  1032. {
  1033. var sqlCommand = (SqlCommand)command;
  1034. sqlCommand.CommandType = CommandType.StoredProcedure;
  1035. List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
  1036. // Create an SqlMetaData object that describes our table type.
  1037. Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
  1038. foreach (int n in numbers)
  1039. {
  1040. // Create a new record, using the metadata array above.
  1041. Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
  1042. rec.SetInt32(0, n); // Set the value.
  1043. number_list.Add(rec); // Add it to the list.
  1044. }
  1045. // Add the table parameter.
  1046. var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured);
  1047. p.Direction = ParameterDirection.Input;
  1048. p.TypeName = "int_list_type";
  1049. p.Value = number_list;
  1050. }
  1051. }
  1052. // SQL Server specific test to demonstrate TVP
  1053. public void TestTVP()
  1054. {
  1055. try
  1056. {
  1057. connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
  1058. connection.Execute("CREATE PROC get_ints @ints int_list_type READONLY AS select * from @ints");
  1059. var nums = connection.Query<int>("get_ints", new IntDynamicParam(new int[] { 1, 2, 3 })).ToList();
  1060. nums[0].IsEqualTo(1);
  1061. nums[1].IsEqualTo(2);
  1062. nums[2].IsEqualTo(3);
  1063. nums.Count.IsEqualTo(3);
  1064. }
  1065. finally
  1066. {
  1067. try
  1068. {
  1069. connection.Execute("DROP PROC get_ints");
  1070. }
  1071. finally
  1072. {
  1073. connection.Execute("DROP TYPE int_list_type");
  1074. }
  1075. }
  1076. }
  1077. class DynamicParameterWithIntTVP : Dapper.DynamicParameters, Dapper.SqlMapper.IDynamicParameters
  1078. {
  1079. IEnumerable<int> numbers;
  1080. public DynamicParameterWithIntTVP(IEnumerable<int> numbers)
  1081. {
  1082. this.numbers = numbers;
  1083. }
  1084. public new void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
  1085. {
  1086. base.AddParameters(command, identity);
  1087. var sqlCommand = (SqlCommand)command;
  1088. sqlCommand.CommandType = CommandType.StoredProcedure;
  1089. List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
  1090. // Create an SqlMetaData object that describes our table type.
  1091. Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
  1092. foreach (int n in numbers)
  1093. {
  1094. // Create a new record, using the metadata array above.
  1095. Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
  1096. rec.SetInt32(0, n); // Set the value.
  1097. number_list.Add(rec); // Add it to the list.
  1098. }
  1099. // Add the table parameter.
  1100. var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured);
  1101. p.Direction = ParameterDirection.Input;
  1102. p.TypeName = "int_list_type";
  1103. p.Value = number_list;
  1104. }
  1105. }
  1106. public void TestTVPWithAdditionalParams()
  1107. {
  1108. try
  1109. {
  1110. connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
  1111. 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");
  1112. var dynamicParameters = new DynamicParameterWithIntTVP(new int[] { 1, 2, 3 });
  1113. dynamicParameters.AddDynamicParams(new { stringParam = "stringParam", dateParam = new DateTime(2012, 1, 1) });
  1114. var results = connection.Query("get_values", dynamicParameters, commandType: CommandType.StoredProcedure).ToList();
  1115. results.Count.IsEqualTo(3);
  1116. for (int i = 0; i < results.Count; i++)
  1117. {
  1118. var result = results[i];
  1119. Assert.IsEqualTo(i + 1, result.n);
  1120. Assert.IsEqualTo("stringParam", result.stringParam);
  1121. Assert.IsEqualTo(new DateTime(2012, 1, 1), result.dateParam);
  1122. }
  1123. }
  1124. finally
  1125. {
  1126. try
  1127. {
  1128. connection.Execute("DROP PROC get_values");
  1129. }
  1130. finally
  1131. {
  1132. connection.Execute("DROP TYPE int_list_type");
  1133. }
  1134. }
  1135. }
  1136. class Parent
  1137. {
  1138. public int Id { get; set; }
  1139. public readonly List<Child> Children = new List<Child>();
  1140. }
  1141. class Child
  1142. {
  1143. public int Id { get; set; }
  1144. }
  1145. public void ParentChildIdentityAssociations()
  1146. {
  1147. var lookup = new Dictionary<int, Parent>();
  1148. 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",
  1149. (parent, child) =>
  1150. {
  1151. Parent found;
  1152. if (!lookup.TryGetValue(parent.Id, out found))
  1153. {
  1154. lookup.Add(parent.Id, found = parent);
  1155. }
  1156. found.Children.Add(child);
  1157. return found;
  1158. }).Distinct().ToDictionary(p => p.Id);
  1159. parents.Count().IsEqualTo(3);
  1160. parents[1].Children.Select(c => c.Id).SequenceEqual(new[] { 1, 2, 4 }).IsTrue();
  1161. parents[2].Children.Select(c => c.Id).SequenceEqual(new[] { 3 }).IsTrue();
  1162. parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue();
  1163. }
  1164. /* TODO:
  1165. *
  1166. public void TestMagicParam()
  1167. {
  1168. // magic params allow you to pass in single params without using an anon class
  1169. // this test fails for now, but I would like to support a single param by parsing the sql with regex and remapping.
  1170. var first = connection.Query("select @a as a", 1).First();
  1171. Assert.IsEqualTo(first.a, 1);
  1172. }
  1173. * */
  1174. class WithBizarreData
  1175. {
  1176. public GenericUriParser Foo { get; set; }
  1177. public int Bar { get; set; }
  1178. }
  1179. public void TestUnexpectedDataMessage()
  1180. {
  1181. string msg = null;
  1182. try
  1183. {
  1184. connection.Query<int>("select count(1) where 1 = @Foo", new WithBizarreData { Foo = new GenericUriParser(GenericUriParserOptions.Default), Bar = 23 }).First();
  1185. }
  1186. catch (Exception ex)
  1187. {
  1188. msg = ex.Message;
  1189. }
  1190. msg.IsEqualTo("The member Foo of type System.GenericUriParser cannot be used as a parameter value");
  1191. }
  1192. public void TestUnexpectedButFilteredDataMessage()
  1193. {
  1194. int i = connection.Query<int>("select @Bar", new WithBizarreData { Foo = new GenericUriParser(GenericUriParserOptions.Default), Bar = 23 }).Single();
  1195. i.IsEqualTo(23);
  1196. }
  1197. class WithCharValue
  1198. {
  1199. public char Value { get; set; }
  1200. public char? ValueNullable { get; set; }
  1201. }
  1202. public void TestCharInputAndOutput()
  1203. {
  1204. const char test = '〠';
  1205. char c = connection.Query<char>("select @c", new { c = test }).Single();
  1206. c.IsEqualTo(test);
  1207. var obj = connection.Query<WithCharValue>("select @Value as Value", new WithCharValue { Value = c }).Single();
  1208. obj.Value.IsEqualTo(test);
  1209. }
  1210. public void TestNullableCharInputAndOutputNonNull()
  1211. {
  1212. char? test = '〠';
  1213. char? c = connection.Query<char?>("select @c", new { c = test }).Single();
  1214. c.IsEqualTo(test);
  1215. var obj = connection.Query<WithCharValue>("select @ValueNullable as ValueNullable", new WithCharValue { ValueNullable = c }).Single();
  1216. obj.ValueNullable.IsEqualTo(test);
  1217. }
  1218. public void TestNullableCharInputAndOutputNull()
  1219. {
  1220. char? test = null;
  1221. char? c = connection.Query<char?>("select @c", new { c = test }).Single();
  1222. c.IsEqualTo(test);
  1223. var obj = connection.Query<WithCharValue>("select @ValueNullable as ValueNullable", new WithCharValue { ValueNullable = c }).Single();
  1224. obj.ValueNullable.IsEqualTo(test);
  1225. }
  1226. public void TestInvalidSplitCausesNiceError()
  1227. {
  1228. try
  1229. {
  1230. connection.Query<User, User, User>("select 1 A, 2 B, 3 C", (x, y) => x);
  1231. }
  1232. catch (ArgumentException)
  1233. {
  1234. // expecting an app exception due to multi mapping being bodged
  1235. }
  1236. try
  1237. {
  1238. connection.Query<dynamic, dynamic, dynamic>("select 1 A, 2 B, 3 C", (x, y) => x);
  1239. }
  1240. catch (ArgumentException)
  1241. {
  1242. // expecting an app exception due to multi mapping being bodged
  1243. }
  1244. }
  1245. class Comment
  1246. {
  1247. public int Id { get; set; }
  1248. public string CommentData { get; set; }
  1249. }
  1250. public void TestMultiMapThreeTypesWithGridReader()
  1251. {
  1252. var createSql = @"
  1253. create table #Users (Id int, Name varchar(20))
  1254. create table #Posts (Id int, OwnerId int, Content varchar(20))
  1255. create table #Comments (Id int, PostId int, CommentData varchar(20))
  1256. insert #Users values(99, 'Sam')
  1257. insert #Users values(2, 'I am')
  1258. insert #Posts values(1, 99, 'Sams Post1')
  1259. insert #Posts values(2, 99, 'Sams Post2')
  1260. insert #Posts values(3, null, 'no ones post')
  1261. insert #Comments values(1, 1, 'Comment 1')";
  1262. connection.Execute(createSql);
  1263. var sql = @"SELECT p.* FROM #Posts p
  1264. select p.*, u.Id, u.Name + '0' Name, c.Id, c.CommentData from #Posts p
  1265. left join #Users u on u.Id = p.OwnerId
  1266. left join #Comments c on c.postId = p.Id
  1267. where p.Id = 1
  1268. Order by p.Id";
  1269. var grid = connection.QueryMultiple(sql);
  1270. var post1 = grid.Read<Post>().ToList();
  1271. var post2 = grid.Read<Post, User, Comment, Post>((post, user, comment) => { post.Owner = user; post.Comment = comment; return post; }).SingleOrDefault();
  1272. post2.Comment.Id.IsEqualTo(1);
  1273. post2.Owner.Id.IsEqualTo(99);
  1274. connection.Execute("drop table #Users drop table #Posts drop table #Comments");
  1275. }
  1276. public void TestReadDynamicWithGridReader()
  1277. {
  1278. var createSql = @"
  1279. create table #Users (Id int, Name varchar(20))
  1280. create table #Posts (Id int, OwnerId int, Content varchar(20))
  1281. insert #Users values(99, 'Sam')
  1282. insert #Users values(2, 'I am')
  1283. insert #Posts values(1, 99, 'Sams Post1')
  1284. insert #Posts values(2, 99, 'Sams Post2')
  1285. insert #Posts values(3, null, 'no ones post')";
  1286. connection.Execute(createSql);
  1287. var sql = @"SELECT * FROM #Users ORDER BY Id
  1288. SELECT * FROM #Posts ORDER BY Id DESC";
  1289. var grid = connection.QueryMultiple(sql);
  1290. var users = grid.Read().ToList();
  1291. var posts = grid.Read().ToList();
  1292. users.Count.IsEqualTo(2);
  1293. posts.Count.IsEqualTo(3);
  1294. ((int)users.First().Id).IsEqualTo(2);
  1295. ((int)posts.First().Id).IsEqualTo(3);
  1296. connection.Execute("drop table #Users drop table #Posts");
  1297. }
  1298. public void TestDynamicParamNullSupport()
  1299. {
  1300. var p = new DynamicParameters();
  1301. p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
  1302. connection.Execute("select @b = null", p);
  1303. p.Get<int?>("@b").IsNull();
  1304. }
  1305. class Foo1
  1306. {
  1307. #pragma warning disable 0649
  1308. public int Id;
  1309. #pragma warning restore 0649
  1310. public int BarId { get; set; }
  1311. }
  1312. class Bar1
  1313. {
  1314. #pragma warning disable 0649
  1315. public int BarId;
  1316. #pragma warning restore 0649
  1317. public string Name { get; set; }
  1318. }
  1319. public void TestMultiMapperIsNotConfusedWithUnorderedCols()
  1320. {
  1321. 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();
  1322. result.Item1.Id.IsEqualTo(1);
  1323. result.Item1.BarId.IsEqualTo(2);
  1324. result.Item2.BarId.IsEqualTo(3);
  1325. result.Item2.Name.IsEqualTo("a");
  1326. }
  1327. public void TestLinqBinaryToClass()
  1328. {
  1329. byte[] orig = new byte[20];
  1330. new Random(123456).NextBytes(orig);
  1331. var input = new System.Data.Linq.Binary(orig);
  1332. var output = connection.Query<WithBinary>("select @input as [Value]", new { input }).First().Value;
  1333. output.ToArray().IsSequenceEqualTo(orig);
  1334. }
  1335. public void TestLinqBinaryRaw()
  1336. {
  1337. byte[] orig = new byte[20];
  1338. new Random(123456).NextBytes(orig);
  1339. var input = new System.Data.Linq.Binary(orig);
  1340. var output = connection.Query<System.Data.Linq.Binary>("select @input as [Value]", new { input }).First();
  1341. output.ToArray().IsSequenceEqualTo(orig);
  1342. }
  1343. class WithBinary
  1344. {
  1345. public System.Data.Linq.Binary Value { get; set; }
  1346. }
  1347. class WithPrivateConstructor
  1348. {
  1349. public int Foo { get; set; }
  1350. private WithPrivateConstructor() { }
  1351. }
  1352. public void TestWithNonPublicConstructor()
  1353. {
  1354. var output = connection.Query<WithPrivateConstructor>("select 1 as Foo").First();
  1355. output.Foo.IsEqualTo(1);
  1356. }
  1357. public void TestAppendingAnonClasses()
  1358. {
  1359. DynamicParameters p = new DynamicParameters();
  1360. p.AddDynamicParams(new { A = 1, B = 2 });
  1361. p.AddDynamicParams(new { C = 3, D = 4 });
  1362. var result = connection.Query("select @A a,@B b,@C c,@D d", p).Single();
  1363. ((int)result.a).IsEqualTo(1);
  1364. ((int)result.b).IsEqualTo(2);
  1365. ((int)result.c).IsEqualTo(3);
  1366. ((int)result.d).IsEqualTo(4);
  1367. }
  1368. public void TestAppendingADictionary()
  1369. {
  1370. var dictionary = new Dictionary<string, object>();
  1371. dictionary.Add("A", 1);
  1372. dictionary.Add("B", "two");
  1373. DynamicParameters p = new DynamicParameters();
  1374. p.AddDynamicParams(dictionary);
  1375. var result = connection.Query("select @A a, @B b", p).Single();
  1376. ((int)result.a).IsEqualTo(1);
  1377. ((string)result.b).IsEqualTo("two");
  1378. }
  1379. public void TestAppendingAnExpandoObject()
  1380. {
  1381. dynamic expando = new System.Dynamic.ExpandoObject();
  1382. expando.A = 1;
  1383. expando.B = "two";
  1384. DynamicParameters p = new DynamicParameters();
  1385. p.AddDynamicParams(expando);
  1386. var result = connection.Query("select @A a, @B b", p).Single();
  1387. ((int)result.a).IsEqualTo(1);
  1388. ((string)result.b).IsEqualTo("two");
  1389. }
  1390. public void TestAppendingAList()
  1391. {
  1392. DynamicParameters p = new DynamicParameters();
  1393. var list = new int[] { 1, 2, 3 };
  1394. p.AddDynamicParams(new { list });
  1395. 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();
  1396. result[0].IsEqualTo(1);
  1397. result[1].IsEqualTo(2);
  1398. result[2].IsEqualTo(3);
  1399. }
  1400. public void TestAppendingAListAsDictionary()
  1401. {
  1402. DynamicParameters p = new DynamicParameters();
  1403. var list = new int[] { 1, 2, 3 };
  1404. var args = new Dictionary<string, object>();
  1405. args.Add("ids", list);
  1406. p.AddDynamicParams(args);
  1407. 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();
  1408. result[0].IsEqualTo(1);
  1409. result[1].IsEqualTo(2);
  1410. result[2].IsEqualTo(3);
  1411. }
  1412. public void TestAppendingAListByName()
  1413. {
  1414. DynamicParameters p = new DynamicParameters();
  1415. var list = new int[] { 1, 2, 3 };
  1416. p.Add("ids", list);
  1417. 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();
  1418. result[0].IsEqualTo(1);
  1419. result[1].IsEqualTo(2);
  1420. result[2].IsEqualTo(3);
  1421. }
  1422. public void TestUniqueIdentifier()
  1423. {
  1424. var guid = Guid.NewGuid();
  1425. var result = connection.Query<Guid>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
  1426. result.IsEqualTo(guid);
  1427. }
  1428. public void TestNullableUniqueIdentifierNonNull()
  1429. {
  1430. Guid? guid = Guid.NewGuid();
  1431. var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
  1432. result.IsEqualTo(guid);
  1433. }
  1434. public void TestNullableUniqueIdentifierNull()
  1435. {
  1436. Guid? guid = null;
  1437. var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
  1438. result.IsEqualTo(guid);
  1439. }
  1440. public void WorkDespiteHavingWrongStructColumnTypes()
  1441. {
  1442. var hazInt = connection.Query<CanHazInt>("select cast(1 as bigint) Value").Single();
  1443. hazInt.Value.Equals(1);
  1444. }
  1445. public void TestProcWithOutParameter()
  1446. {
  1447. connection.Execute(
  1448. @"CREATE PROCEDURE #TestProcWithOutParameter
  1449. @ID int output,
  1450. @Foo varchar(100),
  1451. @Bar int
  1452. AS
  1453. SET @ID = @Bar + LEN(@Foo)");
  1454. var obj = new
  1455. {
  1456. ID = 0,
  1457. Foo = "abc",
  1458. Bar = 4
  1459. };
  1460. var args = new DynamicParameters(obj);
  1461. args.Add("ID", 0, direction: ParameterDirection.Output);
  1462. connection.Execute("#TestProcWithOutParameter", args, commandType: CommandType.StoredProcedure);
  1463. args.Get<int>("ID").IsEqualTo(7);
  1464. }
  1465. public void TestProcWithOutAndReturnParameter()
  1466. {
  1467. connection.Execute(
  1468. @"CREATE PROCEDURE #TestProcWithOutAndReturnParameter
  1469. @ID int output,
  1470. @Foo varchar(100),
  1471. @Bar int
  1472. AS
  1473. SET @ID = @Bar + LEN(@Foo)
  1474. RETURN 42");
  1475. var obj = new
  1476. {
  1477. ID = 0,
  1478. Foo = "abc",
  1479. Bar = 4
  1480. };
  1481. var args = new DynamicParameters(obj);
  1482. args.Add("ID", 0, direction: ParameterDirection.Output);
  1483. args.Add("result", 0, direction: ParameterDirection.ReturnValue);
  1484. connection.Execute("#TestProcWithOutAndReturnParameter", args, commandType: CommandType.StoredProcedure);
  1485. args.Get<int>("ID").IsEqualTo(7);
  1486. args.Get<int>("result").IsEqualTo(42);
  1487. }
  1488. struct CanHazInt
  1489. {
  1490. public int Value { get; set; }
  1491. }
  1492. public void TestInt16Usage()
  1493. {
  1494. connection.Query<short>("select cast(42 as smallint)").Single().IsEqualTo((short)42);
  1495. connection.Query<short?>("select cast(42 as smallint)").Single().IsEqualTo((short?)42);
  1496. connection.Query<short?>("select cast(null as smallint)").Single().IsEqualTo((short?)null);
  1497. connection.Query<ShortEnum>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum)42);
  1498. connection.Query<ShortEnum?>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum?)42);
  1499. connection.Query<ShortEnum?>("select cast(null as smallint)").Single().IsEqualTo((ShortEnum?)null);
  1500. var row =
  1501. connection.Query<WithInt16Values>(
  1502. "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")
  1503. .Single();
  1504. row.NonNullableInt16.IsEqualTo((short)1);
  1505. row.NullableInt16.IsEqualTo((short)2);
  1506. row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Three);
  1507. row.NullableInt16Enum.IsEqualTo(ShortEnum.Four);
  1508. row =
  1509. connection.Query<WithInt16Values>(
  1510. "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")
  1511. .Single();
  1512. row.NonNullableInt16.IsEqualTo((short)5);
  1513. row.NullableInt16.IsEqualTo((short?)null);
  1514. row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Six);
  1515. row.NullableInt16Enum.IsEqualTo((ShortEnum?)null);
  1516. }
  1517. public void TestInt32Usage()
  1518. {
  1519. connection.Query<int>("select cast(42 as int)").Single().IsEqualTo((int)42);
  1520. connection.Query<int?>("select cast(42 as int)").Single().IsEqualTo((int?)42);
  1521. connection.Query<int?>("select cast(null as int)").Single().IsEqualTo((int?)null);
  1522. connection.Query<IntEnum>("select cast(42 as int)").Single().IsEqualTo((IntEnum)42);
  1523. connection.Query<IntEnum?>("select cast(42 as int)").Single().IsEqualTo((IntEnum?)42);
  1524. connection.Query<IntEnum?>("select cast(null as int)").Single().IsEqualTo((IntEnum?)null);
  1525. var row =
  1526. connection.Query<WithInt32Values>(
  1527. "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")
  1528. .Single();
  1529. row.NonNullableInt32.IsEqualTo((int)1);
  1530. row.NullableInt32.IsEqualTo((int)2);
  1531. row.NonNullableInt32Enum.IsEqualTo(IntEnum.Three);
  1532. row.NullableInt32Enum.IsEqualTo(IntEnum.Four);
  1533. row =
  1534. connection.Query<WithInt32Values>(
  1535. "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")
  1536. .Single();
  1537. row.NonNullableInt32.IsEqualTo((int)5);
  1538. row.NullableInt32.IsEqualTo((int?)null);
  1539. row.NonNullableInt32Enum.IsEqualTo(IntEnum.Six);
  1540. row.NullableInt32Enum.IsEqualTo((IntEnum?)null);
  1541. }
  1542. public class WithInt16Values
  1543. {
  1544. public short NonNullableInt16 { get; set; }
  1545. public short? NullableInt16 { get; set; }
  1546. public ShortEnum NonNullableInt16Enum { get; set; }
  1547. public ShortEnum? NullableInt16Enum { get; set; }
  1548. }
  1549. public enum ShortEnum : short
  1550. {
  1551. Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
  1552. }
  1553. public class WithInt32Values
  1554. {
  1555. public int NonNullableInt32 { get; set; }
  1556. public int? NullableInt32 { get; set; }
  1557. public IntEnum NonNullableInt32Enum { get; set; }
  1558. public IntEnum? NullableInt32Enum { get; set; }
  1559. }
  1560. public enum IntEnum : int
  1561. {
  1562. Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
  1563. }
  1564. public void TestTransactionCommit()
  1565. {
  1566. try
  1567. {
  1568. connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
  1569. using (var transaction = connection.BeginTransaction())
  1570. {
  1571. connection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');", transaction: transaction);
  1572. transaction.Commit();
  1573. }
  1574. connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(1);
  1575. }
  1576. finally
  1577. {
  1578. connection.Execute("drop table #TransactionTest;");
  1579. }
  1580. }
  1581. public void TestTransactionRollback()
  1582. {
  1583. connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
  1584. try
  1585. {
  1586. using (var transaction = connection.BeginTransaction())
  1587. {
  1588. connection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');", transaction: transaction);
  1589. transaction.Rollback();
  1590. }
  1591. connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(0);
  1592. }
  1593. finally
  1594. {
  1595. connection.Execute("drop table #TransactionTest;");
  1596. }
  1597. }
  1598. public void TestCommandWithInheritedTransaction()
  1599. {
  1600. connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
  1601. try
  1602. {
  1603. using (var transaction = connection.BeginTransaction())
  1604. {
  1605. var transactedConnection = new TransactedConnection(connection, transaction);
  1606. transactedConnection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');");
  1607. transaction.Rollback();
  1608. }
  1609. connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(0);
  1610. }
  1611. finally
  1612. {
  1613. connection.Execute("drop table #TransactionTest;");
  1614. }
  1615. }
  1616. public void TestReaderWhenResultsChange()
  1617. {
  1618. try
  1619. {
  1620. connection.Execute("create table #ResultsChange (X int);create table #ResultsChange2 (Y int);insert #ResultsChange (X) values(1);insert #ResultsChange2 (Y) values(1);");
  1621. var obj1 = connection.Query<ResultsChangeType>("select * from #ResultsChange").Single();
  1622. obj1.X.IsEqualTo(1);
  1623. obj1.Y.IsEqualTo(0);
  1624. obj1.Z.IsEqualTo(0);
  1625. var obj2 = connection.Query<ResultsChangeType>("select * from #ResultsChange rc inner join #ResultsChange2 rc2 on rc2.Y=rc.X").Single();
  1626. obj2.X.IsEqualTo(1);
  1627. obj2.Y.IsEqualTo(1);
  1628. obj2.Z.IsEqualTo(0);
  1629. connection.Execute("alter table #ResultsChange add Z int null");
  1630. connection.Execute("update #ResultsChange set Z = 2");
  1631. var obj3 = connection.Query<ResultsChangeType>("select * from #ResultsChange").Single();
  1632. obj3.X.IsEqualTo(1);
  1633. obj3.Y.IsEqualTo(0);
  1634. obj3.Z.IsEqualTo(2);
  1635. var obj4 = connection.Query<ResultsChangeType>("select * from #ResultsChange rc inner join #ResultsChange2 rc2 on rc2.Y=rc.X").Single();
  1636. obj4.X.IsEqualTo(1);
  1637. obj4.Y.IsEqualTo(1);
  1638. obj4.Z.IsEqualTo(2);
  1639. } finally
  1640. {
  1641. connection.Execute("drop table #ResultsChange;drop table #ResultsChange2;");
  1642. }
  1643. }
  1644. class ResultsChangeType
  1645. {
  1646. public int X { get; set; }
  1647. public int Y { get; set; }
  1648. public int Z { get; set; }
  1649. }
  1650. public void TestCustomTypeMap()
  1651. {
  1652. // default mapping
  1653. var item = connection.Query<TypeWithMapping>("Select 'AVal' as A, 'BVal' as B").Single();
  1654. item.A.IsEqualTo("AVal");
  1655. item.B.IsEqualTo("BVal");
  1656. // custom mapping
  1657. var map = new CustomPropertyTypeMap(typeof(TypeWithMapping),
  1658. (type, columnName) => type.GetProperties().Where(prop => prop.GetCustomAttributes(false).OfType<DescriptionAttribute>().Any(attr => attr.Description == columnName)).FirstOrDefault());
  1659. Dapper.SqlMapper.SetTypeMap(typeof(TypeWithMapping), map);
  1660. item = connection.Query<TypeWithMapping>("Select 'AVal' as A, 'BVal' as B").Single();
  1661. item.A.IsEqualTo("BVal");
  1662. item.B.IsEqualTo("AVal");
  1663. // reset to default
  1664. Dapper.SqlMapper.SetTypeMap(typeof(TypeWithMapping), null);
  1665. item = connection.Query<TypeWithMapping>("Select 'AVal' as A, 'BVal' as B").Single();
  1666. item.A.IsEqualTo("AVal");
  1667. item.B.IsEqualTo("BVal");
  1668. }
  1669. public class TypeWithMapping
  1670. {
  1671. [Description("B")]
  1672. public string A { get; set; }
  1673. [Description("A")]
  1674. public string B { get; set; }
  1675. }
  1676. public class WrongTypes
  1677. {
  1678. public int A { get; set; }
  1679. public double B { get; set; }
  1680. public long C { get; set; }
  1681. public bool D { get; set; }
  1682. }
  1683. public void TestWrongTypes_WithRightTypes()
  1684. {
  1685. 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();
  1686. item.A.Equals(1);
  1687. item.B.Equals(2.0);
  1688. item.C.Equals(3L);
  1689. item.D.Equals(true);
  1690. }
  1691. public void TestWrongTypes_WithWrongTypes()
  1692. {
  1693. 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();
  1694. item.A.Equals(1);
  1695. item.B.Equals(2.0);
  1696. item.C.Equals(3L);
  1697. item.D.Equals(true);
  1698. }
  1699. public void Test_AddDynamicParametersRepeatedShouldWork()
  1700. {
  1701. var args = new DynamicParameters();
  1702. args.AddDynamicParams(new { Foo = 123 });
  1703. args.AddDynamicParams(new { Foo = 123 });
  1704. int i = connection.Query<int>("select @Foo", args).Single();
  1705. i.IsEqualTo(123);
  1706. }
  1707. public class ParameterWithIndexer
  1708. {
  1709. public int A { get; set; }
  1710. public virtual string this[string columnName]
  1711. {
  1712. get { return null; }
  1713. set { }
  1714. }
  1715. }
  1716. public void TestParameterWithIndexer()
  1717. {
  1718. connection.Execute(@"create proc #TestProcWithIndexer
  1719. @A int
  1720. as
  1721. begin
  1722. select @A
  1723. end");
  1724. var item = connection.Query<int>("#TestProcWithIndexer", new ParameterWithIndexer(), commandType: CommandType.StoredProcedure).Single();
  1725. }
  1726. public void Issue_40_AutomaticBoolConversion()
  1727. {
  1728. var user = connection.Query<Issue40_User>("select UserId=1,Email='abc',Password='changeme',Active=cast(1 as tinyint)").Single();
  1729. user.Active.IsTrue();
  1730. user.UserID.IsEqualTo(1);
  1731. user.Email.IsEqualTo("abc");
  1732. user.Password.IsEqualTo("changeme");
  1733. }
  1734. public class Issue40_User
  1735. {
  1736. public Issue40_User()
  1737. {
  1738. Email = Password = String.Empty;
  1739. }
  1740. public int UserID { get; set; }
  1741. public string Email { get; set; }
  1742. public string Password { get; set; }
  1743. public bool Active { get; set; }
  1744. }
  1745. SqlConnection GetClosedConnection()
  1746. {
  1747. var conn = new SqlConnection(connection.ConnectionString);
  1748. if (conn.State != ConnectionState.Closed) throw new InvalidOperationException("should be closed!");
  1749. return conn;
  1750. }
  1751. public void ExecuteFromClosed()
  1752. {
  1753. using (var conn = GetClosedConnection())
  1754. {
  1755. conn.Execute("-- nop");
  1756. conn.State.IsEqualTo(ConnectionState.Closed);
  1757. }
  1758. }
  1759. public void ExecuteInvalidFromClosed()
  1760. {
  1761. using (var conn = GetClosedConnection())
  1762. {
  1763. try
  1764. {
  1765. conn.Execute("nop");
  1766. false.IsEqualTo(true); // shouldn't have got here
  1767. }
  1768. catch
  1769. {
  1770. conn.State.IsEqualTo(ConnectionState.Closed);
  1771. }
  1772. }
  1773. }
  1774. public void QueryFromClosed()
  1775. {
  1776. using (var conn = GetClosedConnection())
  1777. {
  1778. var i = conn.Query<int>("select 1").Single();
  1779. conn.State.IsEqualTo(ConnectionState.Closed);
  1780. i.IsEqualTo(1);
  1781. }
  1782. }
  1783. public void QueryInvalidFromClosed()
  1784. {
  1785. using (var conn = GetClosedConnection())
  1786. {
  1787. try
  1788. {
  1789. conn.Query<int>("select gibberish").Single();
  1790. false.IsEqualTo(true); // shouldn't have got here
  1791. }
  1792. catch
  1793. {
  1794. conn.State.IsEqualTo(ConnectionState.Closed);
  1795. }
  1796. }
  1797. }
  1798. public void QueryMultipleFromClosed()
  1799. {
  1800. using (var conn = GetClosedConnection())
  1801. {
  1802. using (var multi = conn.QueryMultiple("select 1; select 'abc';"))
  1803. {
  1804. multi.Read<int>().Single().IsEqualTo(1);
  1805. multi.Read<string>().Single().IsEqualTo("abc");
  1806. }
  1807. conn.State.IsEqualTo(ConnectionState.Closed);
  1808. }
  1809. }
  1810. public void QueryMultipleInvalidFromClosed()
  1811. {
  1812. using (var conn = GetClosedConnection())
  1813. {
  1814. try
  1815. {
  1816. conn.QueryMultiple("select gibberish");
  1817. false.IsEqualTo(true); // shouldn't have got here
  1818. }
  1819. catch
  1820. {
  1821. conn.State.IsEqualTo(ConnectionState.Closed);
  1822. }
  1823. }
  1824. }
  1825. public void TestMultiSelectWithSomeEmptyGrids()
  1826. {
  1827. using (var reader = connection.QueryMultiple("select 1; select 2 where 1 = 0; select 3 where 1 = 0; select 4;"))
  1828. {
  1829. var one = reader.Read<int>().ToArray();
  1830. var two = reader.Read<int>().ToArray();
  1831. var three = reader.Read<int>().ToArray();
  1832. var four = reader.Read<int>().ToArray();
  1833. try { // only returned four grids; expect a fifth read to fail
  1834. reader.Read<int>();
  1835. throw new InvalidOperationException("this should not have worked!");
  1836. }
  1837. catch (ObjectDisposedException ex) { // expected; success
  1838. ex.Message.IsEqualTo("The reader has been disposed; this can happen after all data has been consumed\r\nObject name: 'Dapper.SqlMapper+GridReader'.");
  1839. }
  1840. one.Length.IsEqualTo(1);
  1841. one[0].IsEqualTo(1);
  1842. two.Length.IsEqualTo(0);
  1843. three.Length.IsEqualTo(0);
  1844. four.Length.IsEqualTo(1);
  1845. four[0].IsEqualTo(4);
  1846. }
  1847. }
  1848. public void TestDynamicMutation()
  1849. {
  1850. var obj = connection.Query("select 1 as [a], 2 as [b], 3 as [c]").Single();
  1851. ((int)obj.a).IsEqualTo(1);
  1852. IDictionary<string,object> dict = obj;
  1853. Assert.Equals(3, dict.Count);
  1854. Assert.IsTrue(dict.Remove("a"));
  1855. Assert.IsFalse(dict.Remove("d"));
  1856. Assert.Equals(2, dict.Count);
  1857. dict.Add("d", 4);
  1858. Assert.Equals(3, dict.Count);
  1859. Assert.Equals("b,c,d", string.Join(",", dict.Keys.OrderBy(x => x)));
  1860. Assert.Equals("2,3,4", string.Join(",", dict.OrderBy(x => x.Key).Select(x => x.Value)));
  1861. Assert.Equals(2, (int)obj.b);
  1862. Assert.Equals(3, (int)obj.c);
  1863. Assert.Equals(4, (int)obj.d);
  1864. try
  1865. {
  1866. ((int)obj.a).IsEqualTo(1);
  1867. throw new InvalidOperationException("should have thrown");
  1868. }
  1869. catch (RuntimeBinderException)
  1870. {
  1871. // pass
  1872. }
  1873. }
  1874. class TransactedConnection : IDbConnection
  1875. {
  1876. IDbConnection _conn;
  1877. IDbTransaction _tran;
  1878. public TransactedConnection(IDbConnection conn, IDbTransaction tran)
  1879. {
  1880. _conn = conn;
  1881. _tran = tran;
  1882. }
  1883. public string ConnectionString { get { return _conn.ConnectionString; } set { _conn.ConnectionString = value; } }
  1884. public int ConnectionTimeout { get { return _conn.ConnectionTimeout; } }
  1885. public string Database { get { return _conn.Database; } }
  1886. public ConnectionState State { get { return _conn.State; } }
  1887. public IDbTransaction BeginTransaction(IsolationLevel il)
  1888. {
  1889. throw new NotImplementedException();
  1890. }
  1891. public IDbTransaction BeginTransaction()
  1892. {
  1893. return _tran;
  1894. }
  1895. public void ChangeDatabase(string databaseName)
  1896. {
  1897. _conn.ChangeDatabase(databaseName);
  1898. }
  1899. public void Close()
  1900. {
  1901. _conn.Close();
  1902. }
  1903. public IDbCommand CreateCommand()
  1904. {
  1905. // The command inherits the "current" transaction.
  1906. var command = _conn.CreateCommand();
  1907. command.Transaction = _tran;
  1908. return command;
  1909. }
  1910. public void Dispose()
  1911. {
  1912. _conn.Dispose();
  1913. }
  1914. public void Open()
  1915. {
  1916. _conn.Open();
  1917. }
  1918. }
  1919. public void TestDapperTableMetadataRetrieval()
  1920. {
  1921. // Test for a bug found in CS 51509960 where the following sequence would result in an InvalidOperationException being
  1922. // thrown due to an attempt to access a disposed of DataReader:
  1923. //
  1924. // - Perform a dynamic query that yields no results
  1925. // - Add data to the source of that query
  1926. // - Perform a the same query again
  1927. connection.Execute("CREATE TABLE #sut (value varchar(10) NOT NULL PRIMARY KEY)");
  1928. connection.Query("SELECT value FROM #sut").IsSequenceEqualTo(Enumerable.Empty<dynamic>());
  1929. connection.Execute("INSERT INTO #sut (value) VALUES ('test')").IsEqualTo(1);
  1930. var result = connection.Query("SELECT value FROM #sut");
  1931. var first = result.First();
  1932. ((string)first.value).IsEqualTo("test");
  1933. }
  1934. #if POSTGRESQL
  1935. class Cat
  1936. {
  1937. public int Id { get; set; }
  1938. public string Breed { get; set; }
  1939. public string Name { get; set; }
  1940. }
  1941. Cat[] Cats = {
  1942. new Cat() { Breed = "Abyssinian", Name="KACTUS"},
  1943. new Cat() { Breed = "Aegean cat", Name="KADAFFI"},
  1944. new Cat() { Breed = "American Bobtail", Name="KANJI"},
  1945. new Cat() { Breed = "Balinese", Name="MACARONI"},
  1946. new Cat() { Breed = "Bombay", Name="MACAULAY"},
  1947. new Cat() { Breed = "Burmese", Name="MACBETH"},
  1948. new Cat() { Breed = "Chartreux", Name="MACGYVER"},
  1949. new Cat() { Breed = "German Rex", Name="MACKENZIE"},
  1950. new Cat() { Breed = "Javanese", Name="MADISON"},
  1951. new Cat() { Breed = "Persian", Name="MAGNA"}
  1952. };
  1953. public void TestPostresqlArrayParameters()
  1954. {
  1955. using (var conn = new NpgsqlConnection("Server=localhost;Port=5432;User Id=dappertest;Password=dapperpass;Database=dappertest;Encoding=UNICODE"))
  1956. {
  1957. conn.Open();
  1958. IDbTransaction transaction = conn.BeginTransaction();
  1959. conn.Execute("create table tcat ( id serial not null, breed character varying(20) not null, name character varying (20) not null);");
  1960. conn.Execute("insert tcat(breed, name) values(:breed, :name) ", Cats);
  1961. var r = conn.Query<Cat>("select * from tcat where id=any(:catids)", new { catids = new[] { 1, 3, 5 } });
  1962. r.Count().IsEqualTo(3);
  1963. r.Count(c => c.Id == 1).IsEqualTo(1);
  1964. r.Count(c => c.Id == 3).IsEqualTo(1);
  1965. r.Count(c => c.Id == 5).IsEqualTo(1);
  1966. transaction.Rollback();
  1967. }
  1968. }
  1969. #endif
  1970. }
  1971. }