MssqlQueryTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using PetaPoco.Core;
  5. using PetaPoco.Tests.Integration.Models;
  6. using Shouldly;
  7. using Xunit;
  8. namespace PetaPoco.Tests.Integration.Databases.MSSQL
  9. {
  10. [Collection("Mssql")]
  11. public class MssqlQueryTests : BaseQueryTests
  12. {
  13. public MssqlQueryTests()
  14. : base(new MssqlDBTestProvider())
  15. {
  16. }
  17. [Fact]
  18. public void Query_ForPocoGivenDbColumPocoOverlapSqlStringAndParameters_ShouldReturnValidPocoCollection()
  19. {
  20. DB.Insert(new PocoOverlapPoco1 { Column1 = "A", Column2 = "B" });
  21. DB.Insert(new PocoOverlapPoco2 { Column1 = "B", Column2 = "A" });
  22. var sql = @"FROM BugInvestigation_64O6LT8U
  23. JOIN BugInvestigation_5TN5C4U4 ON BugInvestigation_64O6LT8U.[ColumnA] = BugInvestigation_5TN5C4U4.[Column2]";
  24. var poco1 = DB.Query<PocoOverlapPoco1>(sql).ToList().Single();
  25. sql = @"FROM BugInvestigation_5TN5C4U4
  26. JOIN BugInvestigation_64O6LT8U ON BugInvestigation_64O6LT8U.[ColumnA] = BugInvestigation_5TN5C4U4.[Column2]";
  27. var poco2 = DB.Query<PocoOverlapPoco2>(sql).ToList().Single();
  28. poco1.Column1.ShouldBe("A");
  29. poco1.Column2.ShouldBe("B");
  30. poco2.Column1.ShouldBe("B");
  31. poco2.Column2.ShouldBe("A");
  32. }
  33. [Fact]
  34. public void Page_ForPocoGivenSqlStringWithEscapedOrderByColumn_ShouldReturnValidPocoCollection()
  35. {
  36. AddPeople(15, 5);
  37. var page = DB.Page<Person>(1, 5, "WHERE 1 = 1 ORDER BY [FullName]");
  38. page.CurrentPage.ShouldBe(1);
  39. page.TotalPages.ShouldBe(4);
  40. page = DB.Page<Person>(2, 5, "WHERE 1 = 1 ORDER BY [FullName]");
  41. page.CurrentPage.ShouldBe(2);
  42. page.TotalPages.ShouldBe(4);
  43. }
  44. [Fact]
  45. public void Query_ForPocoGivenSqlString_GivenSqlStartingWithSet__ShouldReturnValidPocoCollection()
  46. {
  47. AddOrders(12);
  48. var pd = PocoData.ForType(typeof(Order), DB.DefaultMapper);
  49. var sql = "SET CONCAT_NULL_YIELDS_NULL ON;" +
  50. $"SELECT * FROM [{pd.TableInfo.TableName}] WHERE [{pd.Columns.Values.First(c => c.PropertyInfo.Name == "Status").ColumnName}] = @0";
  51. var results = DB.Query<Order>(sql, OrderStatus.Pending).ToList();
  52. results.Count.ShouldBe(3);
  53. results.ForEach(o =>
  54. {
  55. o.PoNumber.ShouldStartWith("PO");
  56. o.Status.ShouldBeOneOf(Enum.GetValues(typeof(OrderStatus)).Cast<OrderStatus>().ToArray());
  57. o.PersonId.ShouldNotBe(Guid.Empty);
  58. o.CreatedOn.ShouldBeLessThanOrEqualTo(new DateTime(1990, 1, 1, 0, 0, 0, DateTimeKind.Utc));
  59. o.CreatedBy.ShouldStartWith("Harry");
  60. });
  61. }
  62. [Fact]
  63. public void Query_ForPocoGivenSqlString_GivenSqlStartingWithDeclare__ShouldReturnValidPocoCollection()
  64. {
  65. AddOrders(12);
  66. var pd = PocoData.ForType(typeof(Order), DB.DefaultMapper);
  67. var sql = "DECLARE @@v INT;" + "SET @@v = 1;" +
  68. $"SELECT * FROM [{pd.TableInfo.TableName}] WHERE [{pd.Columns.Values.First(c => c.PropertyInfo.Name == "Status").ColumnName}] = @0";
  69. var results = DB.Query<Order>(sql, OrderStatus.Pending).ToList();
  70. results.Count.ShouldBe(3);
  71. results.ForEach(o =>
  72. {
  73. o.PoNumber.ShouldStartWith("PO");
  74. o.Status.ShouldBeOneOf(Enum.GetValues(typeof(OrderStatus)).Cast<OrderStatus>().ToArray());
  75. o.PersonId.ShouldNotBe(Guid.Empty);
  76. o.CreatedOn.ShouldBeLessThanOrEqualTo(new DateTime(1990, 1, 1, 0, 0, 0, DateTimeKind.Utc));
  77. o.CreatedBy.ShouldStartWith("Harry");
  78. });
  79. }
  80. [Fact]
  81. public void Query_ForPocoGivenSqlString_GivenSqlStartingWithWith__ShouldReturnValidPocoCollection()
  82. {
  83. AddOrders(12);
  84. var pd = PocoData.ForType(typeof(Order), DB.DefaultMapper);
  85. var columns = string.Join(", ", pd.Columns.Select(c => DB.Provider.EscapeSqlIdentifier(c.Value.ColumnName)));
  86. var sql = string.Format(@"WITH [{0}_CTE] ({1})
  87. AS
  88. (
  89. SELECT {1} FROM {0}
  90. )
  91. SELECT *
  92. FROM [{0}_CTE]
  93. WHERE [{2}] = @0;", pd.TableInfo.TableName, columns, pd.Columns.Values.First(c => c.PropertyInfo.Name == "Status").ColumnName);
  94. var results = DB.Query<Order>(sql, OrderStatus.Pending).ToList();
  95. results.Count.ShouldBe(3);
  96. results.ForEach(o =>
  97. {
  98. o.PoNumber.ShouldStartWith("PO");
  99. o.Status.ShouldBeOneOf(Enum.GetValues(typeof(OrderStatus)).Cast<OrderStatus>().ToArray());
  100. o.PersonId.ShouldNotBe(Guid.Empty);
  101. o.CreatedOn.ShouldBeLessThanOrEqualTo(new DateTime(1990, 1, 1, 0, 0, 0, DateTimeKind.Utc));
  102. o.CreatedBy.ShouldStartWith("Harry");
  103. });
  104. }
  105. [Fact]
  106. public void Query_MultiResultsSet_SingleResultsSetSinglePoco__ShouldReturnValidPocoCollection()
  107. {
  108. AddPeople(1, 0);
  109. var pd = PocoData.ForType(typeof(Person), DB.DefaultMapper);
  110. var sql = "SET CONCAT_NULL_YIELDS_NULL ON;" +
  111. $"SELECT * FROM [{pd.TableInfo.TableName}] WHERE [{pd.Columns.Values.First(c => c.PropertyInfo.Name == "Name").ColumnName}] LIKE @0 + '%'";
  112. List<Person> result;
  113. using (var multi = DB.QueryMultiple(sql, "Peta"))
  114. {
  115. result = multi.Read<Person>().ToList();
  116. }
  117. result.Count.ShouldBe(1);
  118. var person = result.First();
  119. person.Id.ShouldNotBe(Guid.Empty);
  120. person.Name.ShouldStartWith("Peta");
  121. person.Age.ShouldBe(18);
  122. }
  123. [Fact]
  124. public void Query_MultiResultsSet_SingleResultsSetMultiPoco__ShouldReturnValidPocoCollection()
  125. {
  126. AddOrders(1);
  127. var pd = PocoData.ForType(typeof(Person), DB.DefaultMapper);
  128. var od = PocoData.ForType(typeof(Order), DB.DefaultMapper);
  129. var sql = "SET CONCAT_NULL_YIELDS_NULL ON;" +
  130. $"SELECT TOP 1 * FROM [{od.TableInfo.TableName}] o INNER JOIN [{pd.TableInfo.TableName}] p ON p.[{pd.Columns.Values.First(p => p.PropertyInfo.Name == "Id").ColumnName}] = o.[{od.Columns.Values.First(p => p.PropertyInfo.Name == "PersonId").ColumnName}] WHERE [{pd.Columns.Values.First(c => c.PropertyInfo.Name == "Name").ColumnName}] = @0 ORDER BY 1 DESC";
  131. List<Order> result;
  132. using (var multi = DB.QueryMultiple(sql, "Peta0"))
  133. {
  134. result = multi.Read<Order, Person, Order>((o, p) =>
  135. {
  136. o.Person = p;
  137. return o;
  138. }).ToList();
  139. }
  140. result.Count.ShouldBe(1);
  141. var order = result.First();
  142. order.PoNumber.ShouldStartWith("PO");
  143. order.Status.ShouldBeOneOf(Enum.GetValues(typeof(OrderStatus)).Cast<OrderStatus>().ToArray());
  144. order.PersonId.ShouldNotBe(Guid.Empty);
  145. order.CreatedOn.ShouldBeLessThanOrEqualTo(new DateTime(1990, 1, 1, 0, 0, 0, DateTimeKind.Utc));
  146. order.CreatedBy.ShouldStartWith("Harry");
  147. order.Person.ShouldNotBeNull();
  148. order.Person.Id.ShouldNotBe(Guid.Empty);
  149. order.Person.Name.ShouldStartWith("Peta");
  150. order.Person.Age.ShouldBe(18);
  151. }
  152. [Fact]
  153. public void Query_MultiResultsSet_MultiResultSetSinglePoco__ShouldReturnValidPocoCollection()
  154. {
  155. AddOrders(1);
  156. var pd = PocoData.ForType(typeof(Person), DB.DefaultMapper);
  157. var od = PocoData.ForType(typeof(Order), DB.DefaultMapper);
  158. var sql =
  159. $"SET CONCAT_NULL_YIELDS_NULL ON;SELECT * FROM [{od.TableInfo.TableName}] o WHERE [{od.Columns.Values.First(c => c.PropertyInfo.Name == "Id").ColumnName}] = @0;SELECT * FROM [{pd.TableInfo.TableName}] p WHERE [{pd.Columns.Values.First(c => c.PropertyInfo.Name == "Name").ColumnName}] = @1;";
  160. Order order;
  161. using (var multi = DB.QueryMultiple(sql, "1", "Peta0"))
  162. {
  163. order = multi.Read<Order>().First();
  164. order.Person = multi.Read<Person>().First();
  165. }
  166. order.PoNumber.ShouldStartWith("PO");
  167. order.Status.ShouldBeOneOf(Enum.GetValues(typeof(OrderStatus)).Cast<OrderStatus>().ToArray());
  168. order.PersonId.ShouldNotBe(Guid.Empty);
  169. order.CreatedOn.ShouldBeLessThanOrEqualTo(new DateTime(1990, 1, 1, 0, 0, 0, DateTimeKind.Utc));
  170. order.CreatedBy.ShouldStartWith("Harry");
  171. order.Person.ShouldNotBeNull();
  172. order.Person.Id.ShouldNotBe(Guid.Empty);
  173. order.Person.Name.ShouldStartWith("Peta");
  174. order.Person.Age.ShouldBe(18);
  175. }
  176. [Fact]
  177. public void Query_MultiResultsSet_MultiResultSetMultiPoco__ShouldReturnValidPocoCollection()
  178. {
  179. AddOrders(12);
  180. var pd = PocoData.ForType(typeof(Person), DB.DefaultMapper);
  181. var od = PocoData.ForType(typeof(Order), DB.DefaultMapper);
  182. var old = PocoData.ForType(typeof(OrderLine), DB.DefaultMapper);
  183. var sql = "SET CONCAT_NULL_YIELDS_NULL ON;" +
  184. $"SELECT * FROM [{od.TableInfo.TableName}] o INNER JOIN [{pd.TableInfo.TableName}] p ON p.[{pd.Columns.Values.First(p => p.PropertyInfo.Name == "Id").ColumnName}] = o.[{od.Columns.Values.First(p => p.PropertyInfo.Name == "PersonId").ColumnName}] ORDER BY o.[{od.Columns.Values.First(p => p.PropertyInfo.Name == "Id").ColumnName}] ASC;SELECT * FROM [{old.TableInfo.TableName}] ol ORDER BY ol.[{old.Columns.Values.First(c => c.PropertyInfo.Name == "OrderId").ColumnName}] ASC";
  185. List<Order> results;
  186. using (var multi = DB.QueryMultiple(sql))
  187. {
  188. results = multi.Read<Order, Person, Order>((o, p) =>
  189. {
  190. o.Person = p;
  191. return o;
  192. }).ToList();
  193. var orderLines = multi.Read<OrderLine>().ToList();
  194. foreach (var order in results)
  195. {
  196. order.OrderLines = orderLines.Where(ol => ol.OrderId == order.Id).ToList();
  197. }
  198. }
  199. results.Count.ShouldBe(12);
  200. results.ForEach(o =>
  201. {
  202. o.PoNumber.ShouldStartWith("PO");
  203. o.Status.ShouldBeOneOf(Enum.GetValues(typeof(OrderStatus)).Cast<OrderStatus>().ToArray());
  204. o.PersonId.ShouldNotBe(Guid.Empty);
  205. o.CreatedOn.ShouldBeLessThanOrEqualTo(new DateTime(1990, 1, 1, 0, 0, 0, DateTimeKind.Utc));
  206. o.CreatedBy.ShouldStartWith("Harry");
  207. o.Person.ShouldNotBeNull();
  208. o.Person.Id.ShouldNotBe(Guid.Empty);
  209. o.Person.Name.ShouldStartWith("Peta");
  210. o.Person.Age.ShouldBeGreaterThanOrEqualTo(18);
  211. o.OrderLines.Count.ShouldBe(2);
  212. var firstOrderLine = o.OrderLines.First();
  213. firstOrderLine.Quantity.ToString().ShouldBe("1");
  214. firstOrderLine.SellPrice.ShouldBe(9.99m);
  215. var secondOrderLine = o.OrderLines.Skip(1).First();
  216. secondOrderLine.Quantity.ToString().ShouldBe("2");
  217. secondOrderLine.SellPrice.ShouldBe(19.98m);
  218. });
  219. }
  220. [ExplicitColumns]
  221. [TableName("BugInvestigation_64O6LT8U")]
  222. public class PocoOverlapPoco1
  223. {
  224. [Column("ColumnA")]
  225. public string Column1 { get; set; }
  226. [Column]
  227. public string Column2 { get; set; }
  228. }
  229. [ExplicitColumns]
  230. [TableName("BugInvestigation_5TN5C4U4")]
  231. public class PocoOverlapPoco2
  232. {
  233. [Column("ColumnA")]
  234. public string Column1 { get; set; }
  235. [Column]
  236. public string Column2 { get; set; }
  237. }
  238. }
  239. }