MQuinn

Dapper Extension Methods (via https://github.com/mgroves/)

Jul 7th, 2016
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.17 KB | None | 0 0
  1. namespace StatementProcessor.DataAccess.Reference
  2. {
  3.     using System.Collections.Generic;
  4.     using System.Data.SQLite;
  5.     using System.Linq;
  6.  
  7.     using Dapper;
  8.  
  9.     using Microsoft.VisualStudio.TestTools.UnitTesting;
  10.  
  11.     [TestClass]
  12.     public class DapperReference
  13.     {
  14.         SQLiteConnection connection;
  15.  
  16.         [TestInitialize]
  17.         public void TestSetup()
  18.         {
  19.             connection = new SQLiteConnection("DataSource=:memory:");
  20.             connection.Open();
  21.         }
  22.  
  23.         [TestCleanup]
  24.         public void TestTeardown()
  25.         {
  26.             connection.Close();
  27.         }
  28.  
  29.         private void DapperExtentions()
  30.         {
  31.             CommandDefinition definition = new CommandDefinition();
  32.             connection.Execute(definition);
  33.             connection.ExecuteScalar(definition);
  34.             connection.ExecuteScalar<dynamic>(definition);
  35.             connection.Query<dynamic>(definition);
  36.             connection.QueryMultiple(definition);
  37.             // along with Async versions
  38.         }
  39.  
  40.         [TestMethod]
  41.         public void ExecuteExample()
  42.         {
  43.             connection.Execute("CREATE TABLE TestTable_0 (Field1 INTEGER, Field2 INTEGER);");
  44.             connection.Execute("INSERT INTO TestTable_0 (Field1, Field2) VALUES (42, 99);");
  45.  
  46.             int count = connection.ExecuteScalar<int>("SELECT COUNT(1) FROM TestTable_0;");
  47.  
  48.             Assert.AreEqual(1, count);
  49.  
  50.             connection.Execute("UPDATE TestTable_0 SET Field2 = 998");
  51.  
  52.             int field2 = connection.ExecuteScalar<int>("SELECT Field2 FROM TestTable_0;");
  53.             Assert.AreEqual(998, field2);
  54.  
  55.             connection.Execute("DELETE FROM TestTable_0");
  56.             count = connection.ExecuteScalar<int>("SELECT COUNT(1) FROM TestTable_0;");
  57.             Assert.AreEqual(0, count);
  58.  
  59.             connection.Execute("DROP TABLE TestTable_0");
  60.         }
  61.  
  62.         [TestMethod]
  63.         public void ExecuteCanUseParameters()
  64.         {
  65.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  66.             connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  67.                                 new { Name = "Hawthorn", Age = 42 });
  68.  
  69.             int count = connection.ExecuteScalar<int>("SELECT COUNT(1) FROM Person");
  70.             Assert.AreEqual(1, count);
  71.  
  72.             connection.Execute("DROP TABLE Person");
  73.         }
  74.  
  75.         [TestMethod]
  76.         public void ExecuteCanUseTransactions()
  77.         {
  78.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  79.  
  80.             using (SQLiteTransaction transaction = connection.BeginTransaction())
  81.             {
  82.                 connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  83.                                 new { Name = "Hawthorn", Age = 42 });
  84.                 transaction.Commit();
  85.             }
  86.  
  87.             using (SQLiteTransaction transaction = connection.BeginTransaction())
  88.             {
  89.                 connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  90.                                 new { Name = "Claymore", Age = 42 });
  91.                 transaction.Rollback();
  92.             }
  93.  
  94.             int count = connection.ExecuteScalar<int>("SELECT COUNT(1) FROM Person");
  95.             Assert.AreEqual(1, count);
  96.  
  97.             connection.Execute("DROP TABLE Person");
  98.         }
  99.  
  100.         [TestMethod]
  101.         public void UsingQueryDynamic()
  102.         {
  103.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  104.             connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  105.                                 new { Name = "Hawthorn", Age = 42 });
  106.  
  107.             IEnumerable<dynamic> result = connection.Query("SELECT Name, Age FROM Person");
  108.  
  109.             Assert.AreEqual(1, result.Count());
  110.             Assert.AreEqual("Hawthorn", result.First().Name);
  111.             Assert.AreEqual(42, result.First().Age);
  112.  
  113.             connection.Execute("DROP TABLE Person");
  114.         }
  115.  
  116.         [TestMethod]
  117.         public void UsingQueryT()
  118.         {
  119.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  120.             connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  121.                                 new { Name = "Hawthorn", Age = 42 });
  122.  
  123.             IEnumerable<Person> result = connection.Query<Person>("SELECT Name, Age FROM Person");
  124.  
  125.             Assert.AreEqual(1, result.Count());
  126.             Assert.AreEqual("Hawthorn", result.First().Name);
  127.             Assert.AreEqual(42, result.First().Age);
  128.  
  129.             connection.Execute("DROP TABLE Person");
  130.         }
  131.  
  132.         [TestMethod]
  133.         public void MismatchedColumnNames()
  134.         {
  135.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  136.             connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  137.                                 new { Name = "Hawthorn", Age = 42 });
  138.  
  139.             IEnumerable<Person> result =
  140.                 connection.Query<Person>("SELECT Name AS FirstName, Age FROM Person");
  141.  
  142.             Assert.AreEqual(1, result.Count());
  143.             Assert.IsNull(result.First().Name);
  144.             Assert.AreEqual(42, result.First().Age);
  145.  
  146.             connection.Execute("DROP TABLE Person");
  147.         }
  148.  
  149.         [TestMethod]
  150.         public void MultiInsert()
  151.         {
  152.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  153.             connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  154.                                 new[]
  155.                                 {
  156.                                     new { Name = "Hawthorn", Age = 42 },
  157.                                     new { Name = "Claymore", Age =  50 },
  158.                                     new { Name = "Saul", Age =  37 },
  159.                                     new { Name = "Livingstone", Age =  55 },
  160.                                     new { Name = "Morton", Age = 35 },
  161.                                     new { Name = "Stanley", Age = 48 },
  162.                                 });
  163.  
  164.             int count = connection.ExecuteScalar<int>("SELECT COUNT(1) FROM Person");
  165.            
  166.             Assert.AreEqual(6, count);
  167.  
  168.             connection.Execute("DROP TABLE Person");
  169.         }
  170.  
  171.         [TestMethod]
  172.         public void UsingInKeyword()
  173.         {
  174.             connection.Execute("CREATE TABLE Person (Name TEXT, Age INTEGER);");
  175.             connection.Execute("INSERT INTO Person (Name, Age) VALUES (@Name, @Age)",
  176.                                 new[]
  177.                                 {
  178.                                     new { Name = "Hawthorn", Age = 42 },
  179.                                     new { Name = "Claymore", Age =  50 },
  180.                                     new { Name = "Saul", Age =  37 },
  181.                                     new { Name = "Livingstone", Age =  55 },
  182.                                     new { Name = "Morton", Age = 35 },
  183.                                     new { Name = "Stanley", Age = 48 },
  184.                                 });
  185.  
  186.             int count = connection.ExecuteScalar<int>(
  187.                                     "SELECT COUNT(1) FROM Person WHERE Age IN @Ages",
  188.                                     new { Ages = new[] {35, 55 }  });
  189.  
  190.             Assert.AreEqual(2, count);
  191.            
  192.             connection.Execute("DROP TABLE Person");
  193.         }
  194.  
  195.         [TestMethod]
  196.         public void MultiMapDefaultConvention()
  197.         {
  198.             connection.Execute(@"CREATE TABLE ComicBookCompanies (
  199.                                     ComicBookCompanyID INTEGER PRIMARY KEY AUTOINCREMENT,
  200.                                     CompanyName TEXT);");
  201.             int dcID
  202.                 = connection.ExecuteScalar<int>(@"INSERT INTO ComicBookCompanies
  203.                                                     ( CompanyName ) VALUES ( 'D.C.' );
  204.                                                     SELECT last_insert_rowid();");
  205.  
  206.             connection.Execute(@"CREATE TABLE Heroes (
  207.                                         HeroID INTEGER PRIMARY KEY AUTOINCREMENT,
  208.                                         ComicBookCompanyID INTEGER,
  209.                                         HeroName TEXT);");
  210.  
  211.             connection.Execute(@"INSERT INTO Heroes
  212.                                     ( ComicBookCompanyID, HeroName )
  213.                                     VALUES
  214.                                     ( @ComicBookCompanyID, @HeroName );",
  215.                                     new[]{  new { ComicBookCompanyID = dcID, HeroName = "Batman" },
  216.                                             new { ComicBookCompanyID = dcID, HeroName = "Superman"} });
  217.  
  218.             // NOTE: Use of "AS Id" to allow Dapper to default to using Id
  219.             //          to split the returned columns into objects
  220.             string sql = @"SELECT h.HeroID AS Id, h.HeroName,
  221.                                     c.ComicBookCompanyID AS Id, c.CompanyName
  222.                                 FROM Heroes h
  223.                                     INNER JOIN ComicBookCompanies c
  224.                                         ON c.ComicBookCompanyID = h.HeroID";
  225.  
  226.             // connection.Query<FirstObject, SecondObject, ReturnObject>
  227.             Hero firstHero =
  228.                     connection.Query<Hero, ComicBookCompany, Hero>(sql,
  229.                             (hero, company) =>
  230.                             {
  231.                                 hero.ComicBookCompany = company;
  232.                                 return hero;
  233.                             }).First();
  234.  
  235.             Assert.AreEqual("Batman", firstHero.HeroName);
  236.             // Assert.AreEqual(0, firstHero.HeroID);   // Don't like this
  237.             Assert.AreEqual("D.C.", firstHero.ComicBookCompany.CompanyName);
  238.             // Assert.AreEqual(0, firstHero.ComicBookCompany.CompanyID); // Or this
  239.  
  240.             connection.Execute("DROP TABLE ComicBookCompanies");
  241.             connection.Execute("DROP TABLE Heroes");
  242.         }
  243.  
  244.         [TestMethod]
  245.         public void MultiMapCustomSplit_0()
  246.         {
  247.             connection.Execute(@"CREATE TABLE ComicBookCompanies (
  248.                                     ComicBookCompanyID INTEGER PRIMARY KEY AUTOINCREMENT,
  249.                                     CompanyName TEXT);");
  250.             int dcID
  251.                 = connection.ExecuteScalar<int>(@"INSERT INTO ComicBookCompanies
  252.                                                     ( CompanyName ) VALUES ( 'D.C.' );
  253.                                                     SELECT last_insert_rowid();");
  254.  
  255.             connection.Execute(@"CREATE TABLE Heroes (
  256.                                         HeroID INTEGER PRIMARY KEY AUTOINCREMENT,
  257.                                         ComicBookCompanyID INTEGER,
  258.                                         HeroName TEXT);");
  259.  
  260.             connection.Execute(@"INSERT INTO Heroes
  261.                                     ( ComicBookCompanyID, HeroName )
  262.                                     VALUES
  263.                                     ( @ComicBookCompanyID, @HeroName );",
  264.                                     new[]{  new { ComicBookCompanyID = dcID, HeroName = "Batman" },
  265.                                             new { ComicBookCompanyID = dcID, HeroName = "Superman"} });
  266.  
  267.             string sql = @"SELECT h.HeroID, h.HeroName,
  268.                                     c.ComicBookCompanyID, c.CompanyName
  269.                                 FROM Heroes h
  270.                                     INNER JOIN ComicBookCompanies c
  271.                                         ON c.ComicBookCompanyID = h.HeroID";
  272.  
  273.             // connection.Query<FirstObject, SecondObject, ReturnObject>
  274.             // "splitOn" can be a list
  275.             Hero firstHero =
  276.                     connection.Query<Hero, ComicBookCompany, Hero>(sql,
  277.                             (hero, company) =>
  278.                             {
  279.                                 hero.ComicBookCompany = company;
  280.                                 return hero;
  281.                             }, splitOn: "ComicBookCompanyID")
  282.                             .First();
  283.  
  284.             Assert.AreEqual("Batman", firstHero.HeroName);
  285.             Assert.AreEqual("D.C.", firstHero.ComicBookCompany.CompanyName);
  286.  
  287.             connection.Execute("DROP TABLE ComicBookCompanies");
  288.             connection.Execute("DROP TABLE Heroes");
  289.         }
  290.  
  291.         [TestMethod]
  292.         public void MultiMapCustomSplit_1()
  293.         {
  294.             connection.Execute(@"CREATE TABLE ComicBookCompanies (
  295.                                     ComicBookCompanyID INTEGER PRIMARY KEY AUTOINCREMENT,
  296.                                     CompanyName TEXT);");
  297.             int dcID
  298.                 = connection.ExecuteScalar<int>(@"INSERT INTO ComicBookCompanies
  299.                                                     ( CompanyName ) VALUES ( 'D.C.' );
  300.                                                     SELECT last_insert_rowid();");
  301.  
  302.             connection.Execute(@"CREATE TABLE Heroes (
  303.                                         HeroID INTEGER PRIMARY KEY AUTOINCREMENT,
  304.                                         ComicBookCompanyID INTEGER,
  305.                                         HeroName TEXT);");
  306.  
  307.             long batmanID = connection.ExecuteScalar<long>(@"INSERT INTO Heroes
  308.                                     ( ComicBookCompanyID, HeroName )
  309.                                     VALUES
  310.                                     ( @ComicBookCompanyID, @HeroName );
  311.                                     SELECT last_insert_rowid();",
  312.                                      new { ComicBookCompanyID = dcID, HeroName = "Batman" });
  313.  
  314.             connection.Execute(@"CREATE TABLE Sidekicks (
  315.                                         SidekickID INTEGER PRIMARY KEY AUTOINCREMENT,
  316.                                         HeroID INTEGER,
  317.                                         SidekickName TEXT);");
  318.  
  319.             connection.Execute(@"INSERT INTO Sidekicks
  320.                                     ( HeroID, SidekickName )
  321.                                     VALUES
  322.                                     ( @HeroID, @SidekickName );",
  323.                                     new[] { new { HeroID = batmanID, SidekickName = "Robin" } });
  324.  
  325.             string sql = @"SELECT s.SidekickID, s.SidekickName,
  326.                                     h.HeroID, h.HeroName,
  327.                                     c.ComicBookCompanyID, c.CompanyName
  328.                                 FROM  Sidekicks s
  329.                                     INNER JOIN Heroes h
  330.                                         ON s.HeroID = h.HeroID
  331.                                     INNER JOIN  ComicBookCompanies c
  332.                                         ON c.ComicBookCompanyID = h.HeroID";
  333.  
  334.             Sidekick firstSidekick =
  335.                     connection.Query<Sidekick, Hero, ComicBookCompany, Sidekick>(sql,
  336.                             (sidekick, hero, company) =>
  337.                             {
  338.                                 sidekick.Hero = hero;
  339.                                 hero.ComicBookCompany = company;
  340.                                 return sidekick;
  341.                             }, splitOn: "HeroID,ComicBookCompanyID"
  342.                             ).First();
  343.            
  344.             Assert.AreEqual("Robin", firstSidekick.SidekickName);
  345.             Assert.AreEqual("Batman", firstSidekick.Hero.HeroName);
  346.             Assert.AreEqual("D.C.", firstSidekick.Hero.ComicBookCompany.CompanyName);
  347.  
  348.             connection.Execute("DROP TABLE ComicBookCompanies");
  349.             connection.Execute("DROP TABLE Heroes");
  350.             connection.Execute("DROP TABLE Sidekicks");
  351.         }
  352.  
  353.         [TestMethod]
  354.         public void UseLookupForOneToMany()
  355.         {
  356.             connection.Execute(@"CREATE TABLE Starship (
  357.                                     StarshipID INTEGER PRIMARY KEY AUTOINCREMENT,
  358.                                     StarshipName TEXT)");
  359.  
  360.             int shipID = connection.ExecuteScalar<int>(
  361.                                 @"INSERT INTO Starship ( StarshipName )
  362.                                     VALUES ( 'USS Enterprise NCC 1701' );
  363.                                 SELECT last_insert_rowid();");
  364.  
  365.             connection.Execute(@"CREATE TABLE CrewMember (
  366.                                     CrewMemberID INTEGER PRIMARY KEY AUTOINCREMENT,
  367.                                     StarshipID INTEGER,
  368.                                     MemberName TEXT)");
  369.  
  370.             connection.Execute(@"INSERT INTO CrewMember
  371.                                     ( StarshipID, MemberName )
  372.                                     VALUES
  373.                                     ( @StarshipID, @MemberName )",
  374.                                     new[]
  375.                                     {
  376.                                         new { MemberName = "Luke Skywalker", StarshipID = shipID },
  377.                                         new { MemberName = "Gandalf", StarshipID = shipID }
  378.                                     });
  379.  
  380.             string sql = @"SELECT s.StarshipID, s.StarshipName,
  381.                                 c.CrewMemberID, c.StarshipID, c.MemberName
  382.                                 FROM Starship s
  383.                                     INNER JOIN CrewMember c
  384.                                         ON c.StarshipID = s.StarshipID";
  385.  
  386.             List<Starship> lookup = new List<Starship>();
  387.             connection.Query<Starship, CrewMember, Starship>(sql,
  388.                         (starship, crewmember) =>
  389.                         {
  390.                             Starship ship = lookup.FirstOrDefault(s => s.StarshipID == starship.StarshipID);
  391.  
  392.                             if (ship == null)
  393.                             {
  394.                                 lookup.Add(starship);
  395.                                 ship = starship;
  396.                             }
  397.  
  398.                             ship.Crew = ship.Crew ?? new List<CrewMember>();
  399.                             ship.Crew.Add(crewmember);
  400.  
  401.                             return null;
  402.                         }, splitOn: "CrewMemberID");
  403.  
  404.             Assert.AreEqual(1, lookup.Count);
  405.             Assert.AreEqual(2, lookup[0].Crew.Count);
  406.             Assert.AreEqual("Luke Skywalker", lookup[0].Crew[0].MemberName);
  407.             Assert.AreEqual("Gandalf", lookup[0].Crew[1].MemberName);
  408.  
  409.             connection.Execute("DROP TABLE Starship");
  410.             connection.Execute("DROP TABLE CrewMember");
  411.         }
  412.  
  413.         [TestMethod]
  414.         public void MultipleResultsSingleQuery()
  415.         {
  416.             connection.Execute("CREATE TABLE TestTable_0 (Field_0 INTEGER);");
  417.             connection.Execute("CREATE TABLE TestTable_1 (Field_1 INTEGER);");
  418.             connection.Execute("CREATE TABLE TestTable_2 (Field_2 INTEGER);");
  419.  
  420.             connection.Execute("INSERT INTO TestTable_0 (Field_0) VALUES (1)");
  421.             connection.Execute("INSERT INTO TestTable_1 (Field_1) VALUES (2)");
  422.             connection.Execute("INSERT INTO TestTable_2 (Field_2) VALUES (3)");
  423.  
  424.             string sql = @"SELECT Field_0 FROM TestTable_0;
  425.                             SELECT Field_1 FROM TestTable_1;
  426.                             SELECT Field_2 FROM TestTable_2;";
  427.  
  428.             using (SqlMapper.GridReader multiQuery = connection.QueryMultiple(sql))
  429.             {
  430.                 // Check multiQuery.Read<T>()
  431.                 var result0 = multiQuery.Read().First();
  432.                 var result1 = multiQuery.Read().First();
  433.                 var result2 = multiQuery.Read().First();
  434.  
  435.                 Assert.AreEqual(1, result0.Field_0);
  436.                 Assert.AreEqual(2, result1.Field_1);
  437.                 Assert.AreEqual(3, result2.Field_2);
  438.             }
  439.  
  440.             connection.Execute("DROP TABLE TestTable_0");
  441.             connection.Execute("DROP TABLE TestTable_1");
  442.             connection.Execute("DROP TABLE TestTable_2");
  443.         }
  444.  
  445.         [TestMethod]
  446.         [ExpectedException(typeof(SQLiteException))]
  447.         public void InvalidSQL()
  448.         {
  449.             connection.Execute("I am your mother's invalid SQL");
  450.         }
  451.     }
  452.  
  453.     public class ComicBookCompany
  454.     {
  455.         public int CompanyID { get; set; }
  456.         public string CompanyName { get; set; }
  457.     }
  458.  
  459.     public class Hero
  460.     {
  461.         public int HeroID { get; set; }
  462.         public string HeroName { get; set; }
  463.         public ComicBookCompany ComicBookCompany { get; set; }
  464.     }
  465.  
  466.     public class Sidekick
  467.     {
  468.         public int SidekickID { get; set; }
  469.         public string SidekickName { get; set; }
  470.         public Hero Hero { get; set; }
  471.     }
  472.    
  473.     public class Person
  474.     {
  475.         public string Name { get; set; }
  476.         public int Age { get; set; }
  477.     }
  478.  
  479.     public class Starship
  480.     {
  481.         public int StarshipID { get; set; }
  482.         public string StarshipName { get; set; }
  483.         public List<CrewMember> Crew { get; set; }
  484.     }
  485.  
  486.     public class CrewMember
  487.     {
  488.         public int CrewMemberID { get; set; }
  489.         public int StarshipID { get; set; }
  490.         // Heheh ... "Member" name
  491.         public string MemberName { get; set; }
  492.     }
  493. }
  494.  
  495. //Interesting idea for using splitOn
  496. //Found at: http://stackoverflow.com/questions/7472088/correct-use-of-multimapping-in-dapper
  497.  
  498. //  public IEnumerable<TParent> GetParentChild<TParent, TChild>()
  499. //  {
  500. //      var sql = string.Format(@"select * from {0} p
  501. //      inner join {1} c on p.{1}Id = c.Id",
  502. //      typeof(TParent).Name, typeof(TChild).Name);
  503.  
  504. //      Debug.WriteLine(sql);
  505.  
  506. //      var data = _con.Query<TParent, TChild, TParent>(
  507. //          sql,
  508. //          (p, c) =>
  509. //          {
  510. //              p.GetType().GetProperty(typeof (TChild).Name).SetValue(p, c);
  511. //              return p;
  512. //          },
  513. //          splitOn: typeof(TChild).Name + "Id");
  514.  
  515. //     return data;
  516. // }
  517.  
  518. https://github.com/mgroves
Add Comment
Please, Sign In to add comment