Dapper CRUD Win Forms - Part One

Create a SQL Server database with the name "DapperDB"

For purposes of the example, we can restore it from the sample file or use the code given below to create it.

  1. USE [DapperDB]  
  2.   
  3. GO  
  4.   
  5. SET ANSI_NULLS ON  
  6.   
  7. GO  
  8.   
  9. SET QUOTED_IDENTIFIER ON  
  10.   
  11. GO  
  12.   
  13. CREATE TABLE [dbo].[users](  
  14.   
  15. [id] [nvarchar](50) NOT NULL,  
  16.   
  17. [name] [nvarchar](50) NULL,  
  18.   
  19. [address] [nvarchar](50) NULL,  
  20.   
  21. [status] [nvarchar](50) NULL,  
  22.   
  23. CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED  
  24.   
  25. (  
  26.   
  27. [id] ASC  
  28.   
  29. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  30.   
  31. ON [PRIMARY]  
  32.   
  33. GO  
  34.   
  35. USE [DapperDB]  
  36.   
  37. GO  
  38.   
  39. /****** Object: StoredProcedure [dbo].[users_DeleteRow_By_id] Script Date: 06/02/2017 11:13:02 a.m. ******/  
  40.   
  41. SET ANSI_NULLS ON  
  42.   
  43. GO  
  44.   
  45. SET QUOTED_IDENTIFIER ON  
  46.   
  47. GO  
  48.   
  49. CREATE Procedure [dbo].[users_DeleteRow_By_id]  
  50.   
  51. @id nvarchar(50)  
  52.   
  53. As  
  54.   
  55. Begin  
  56.   
  57. Delete users  
  58.   
  59. Where  
  60.   
  61. [id] = @id  
  62.   
  63. End  
  64.   
  65. GO  
  66.   
  67. USE [DapperDB]  
  68.   
  69. GO  
  70.   
  71. SET ANSI_NULLS ON  
  72.   
  73. GO  
  74.   
  75. SET QUOTED_IDENTIFIER ON  
  76.   
  77. GO  
  78.   
  79. CREATE Procedure [dbo].[users_Insert_Update]  
  80.   
  81. @id nvarchar(50),  
  82.   
  83. @name nvarchar(50),  
  84.   
  85. @address nvarchar(50),  
  86.   
  87. @status nvarchar(50)  
  88.   
  89. As  
  90.   
  91. BEGIN  
  92.   
  93. IF NOT EXISTS (SELECT * FROM dbo.users u WHERE u.id = @id)  
  94.   
  95. BEGIN  
  96.   
  97. Insert Into users  
  98.   
  99. ([id],[name],[address],[status])  
  100.   
  101. Values  
  102.   
  103. (@id,@name,@address,@status)  
  104.   
  105. END  
  106.   
  107. ELSE  
  108.   
  109. BEGIN  
  110.   
  111. Update users  
  112.   
  113. Set  
  114.   
  115. [id] = @id,  
  116.   
  117. [name] = @name,  
  118.   
  119. [address] = @address,  
  120.   
  121. [status] = @status  
  122.   
  123. Where [id] = @id  
  124.   
  125. END  
  126.   
  127. End  
  128.   
  129. GO  
  130.   
  131. USE [DapperDB]  
  132.   
  133. GO  
  134.   
  135. SET ANSI_NULLS ON  
  136.   
  137. GO  
  138.   
  139. SET QUOTED_IDENTIFIER ON  
  140.   
  141. GO  
  142.   
  143. CREATE Procedure [dbo].[users_SelectAll]  
  144.   
  145. As  
  146.   
  147. Begin  
  148.   
  149. SELECT dbo.users.id  
  150.   
  151. , dbo.users.name  
  152.   
  153. , dbo.users.address  
  154.   
  155. , dbo.users.status FROM dbo.users  
  156.   
  157. End  
  158.   
  159. GO  
  160.   
  161. USE [DapperDB]  
  162.   
  163. GO  
  164.   
  165. SET ANSI_NULLS ON  
  166.   
  167. GO  
  168.   
  169. SET QUOTED_IDENTIFIER ON  
  170.   
  171. GO  
  172.   
  173. CREATE Procedure [dbo].[users_SelectRow_By_id]  
  174.   
  175. @id nvarchar(50)  
  176.   
  177. As  
  178.   
  179. Begin  
  180.   
  181. Select  
  182.   
  183. dbo.users.id  
  184.   
  185. , dbo.users.name  
  186.   
  187. , dbo.users.address  
  188.   
  189. , dbo.users.status  
  190.   
  191.   
  192. From users  
  193.   
  194. Where  
  195.   
  196. [id] = @id  
  197.   
  198. End  
  199.   
  200. GO  
  201.   
  202. USE [DapperDB]  
  203.   
  204. GO  
  205.   
  206. SET ANSI_NULLS ON  
  207.   
  208. GO  
  209.   
  210. SET QUOTED_IDENTIFIER ON  
  211.   
  212. GO  
  213.   
  214. CREATE Procedure [dbo].[users_SelectwithDate]  
  215.   
  216. As  
  217.   
  218. Begin  
  219.   
  220. SELECT dbo.users.id  
  221.   
  222. , dbo.users.name  
  223.   
  224. , dbo.users.address  
  225.   
  226. , dbo.users.status  
  227.   
  228. , getdate() AS [date]  
  229.   
  230. FROM dbo.users  
  231.   
  232. End  
  233.   
  234. GO  

Create a Windows form C# Application with the name "DapperRepoWinForm"

Add Dapper package to the project.

Click on tools-> NuGet Packages Manager-> Manage NuGet Packages for Solution.


Now, click on Manage Nuget Packages option, then Windows given below will appear.

  • Click on Browse.
  • As shown in the image, type in search box “dapper”.
  • Select Dapper, as shown in the image.
  • Check the project solution.

Click on install button.


Creating folders 

  1. Now, we must create a folder in the project. We'll call it utilities. Inside it, we will create a class named "Globals".

This class will serve to create a variable "stringConn", which contains the information for the login in the database. A constant path with the address of XML file contains the login information. 

  1. using System;  
  2.   
  3. using System.Collections.Generic;  
  4.   
  5. using System.Data;  
  6.   
  7. namespace DapperRepoWinForm.Utilities  
  8. {  
  9.     public static class Globals  
  10.     {  
  11.         public static String stringConn = "";  
  12.         public const string path = "c:\\conn.xml";  
  13.     }  

Now, we will create a class, which we will call "ConnectionDB".

This class is used to read XML file and get the data for the login. Here, you can place the code to encrypt the information. For this example, I do not put it. 

  1. using System.Xml;  
  2.   
  3. namespace DapperRepoWinForm.Utilities  
  4.   
  5. {  
  6.   
  7.    class ConnectionDB  
  8.   
  9.     {  
  10.   
  11.         public static string xml_conn(string path)  
  12.   
  13.         {  
  14.   
  15.             XmlDocument xmlDoc = new XmlDocument();  
  16.   
  17.             xmlDoc.Load(path);  
  18.   
  19.             XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/Table/Conexion");  
  20.   
  21.             string proServer = "", proDatabase = "", proUser = "", proPassword = "";  
  22.   
  23.   
  24.             foreach (XmlNode node in nodeList)  
  25.   
  26.             {  
  27.   
  28.                 proServer = node.SelectSingleNode("Server").InnerText;  
  29.   
  30.                 proDatabase = node.SelectSingleNode("Database").InnerText;  
  31.   
  32.                 proUser = node.SelectSingleNode("User").InnerText;  
  33.   
  34.                 proPassword = node.SelectSingleNode("Password").InnerText;  
  35.   
  36.             }  
  37.   
  38.             return ("Server = " + proServer + "; Database =" + proDatabase + "; User Id = " + proUser + ";Password = " + proPassword + ";");  
  39.   
  40.   
  41.         }  
  42.   
  43.   
  44.     }  
  45.   
  46. }  

We create a folder in the project, which we will call it "Repository". Within this folder, we will create a class called "RepGen" At the beginning, add the code given below.

  1. using System.Data.SqlClient;  
  2.   
  3. using Dapper;  
  4.   
  5. using DapperRepoWinForm.Utilities; 

This class will serve to connect to the database and execute the stored procedures of ype (non query, return scalar or return numeric value).

How does it work

The void connection fills the value of the "with" variable with the connection data to the database.

  1. private void connection()  
  2.     {  
  3.         con = new SqlConnection(Globals.stringConn);  
  4.     }   

The function executeNonQuery executes a no-query stored procedure (like, insert, update, delete).

  1. public string executeNonQuery(string query, DynamicParameters param)  
  2.     {  
  3.          try  
  4.                 {  
  5.   
  6.         connection();  
  7.   
  8.         con.Open();  
  9.   
  10.         con.Execute(query, param, commandType: CommandType.StoredProcedure);  
  11.   
  12.         con.Close();  
  13.   
  14.         return "0";  
  15.   
  16.                 }  
  17.   
  18.          catch (Exception ex)  
  19.   
  20.          {  
  21.   
  22.              return ex.Message;  
  23.          }  
  24.   
  25.     }   

The fuction returnNumericValue executes a stored procedure with numeric return values.

  1. public  string returnNumericValue(string query, DynamicParameters param)  
  2.   
  3.         {  
  4.   
  5.             try  
  6.   
  7.             {  
  8.   
  9.                 string valor = "";  
  10.   
  11.                 param.Add("@output", dbType: DbType.Int32 , direction: ParameterDirection.Output);  
  12.   
  13.                 param.Add("@Returnvalue", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);  
  14.   
  15.                 // Getting Return value    
  16.   
  17.                 connection();  
  18.   
  19.                 con.Open();  
  20.   
  21.                 valor = con.ExecuteScalar<string>(query, param, commandType: CommandType.StoredProcedure);  
  22.   
  23.                 con.Close();  
  24.   
  25.                 return valor;  
  26.   
  27.             }  
  28.   
  29.             catch (Exception ex)  
  30.   
  31.             {  
  32.   
  33.                 return ex.Message;  
  34.   
  35.             }  
  36.   
  37.   
  38.         }  

The returnScalar function executes stored procedures with return values ​​of type scalar.

  1. string returnScalar(string query, DynamicParameters param)  
  2.     {  
  3.   
  4.         try  
  5.   
  6.         {  
  7.   
  8.             string valor = "";  
  9.   
  10.             connection();  
  11.   
  12.             con.Open();  
  13.   
  14.             valor =  con.ExecuteScalar<string>(query, param, commandType: CommandType.StoredProcedure);  
  15.   
  16.             con.Close();  
  17.   
  18.             return valor;  
  19.   
  20.         }  
  21.   
  22.         catch (Exception ex)  
  23.   
  24.         {  
  25.   
  26.             return ex.Message;  
  27.   
  28.         }  
  29.   
  30.   
  31.     }  

We will create a next class named "RepGen"

This class will call the stored procedures that returns groups of data or a class. We will use dapper and fill a non-generic collection of the objects. I use it to fill the grids, which can be accessed individually by an index "Ilist <t>" or we can return a single class (for search purposes).

  1. System;  
  2.   
  3. using System.Collections.Generic;  
  4.   
  5. using System.Linq;  
  6.   
  7. using System.Data.SqlClient;  
  8.   
  9. using Dapper;  
  10.   
  11. using System.Data;  
  12.   
  13. using DapperRepoWinForm.Utilities;  
  14.   
  15. namespace DapperRepoWinForm.Repository  
  16.   
  17. {  
  18.   
  19.     class RepList<T> where T : class  
  20.   
  21.     {  
  22.   
  23.   
  24.         public SqlConnection con;  
  25.   
  26.         private void connection()  
  27.   
  28.         {  
  29.   
  30.             con = new SqlConnection(Globals.stringConn);  
  31.   
  32.         }  
  33.   
  34.         public List<T> returnListClass(string query, DynamicParameters param)  
  35.   
  36.         {  
  37.   
  38.             try  
  39.   
  40.             {  
  41.   
  42.             connection();  
  43.   
  44.             con.Open();  
  45.   
  46.             IList<T> Tlista = SqlMapper.Query<T>(con, query, param, nulltruenull, commandType: CommandType.StoredProcedure).ToList();  
  47.   
  48.             con.Close();  
  49.   
  50.             return Tlista.ToList();  
  51.   
  52.             }  
  53.   
  54.             catch (Exception)  
  55.   
  56.             {  
  57.   
  58.                 throw;  
  59.   
  60.             }  
  61.   
  62.         }  
  63.   
  64.   
  65.         public T returnClass(string query, DynamicParameters param)  
  66.   
  67.         {  
  68.   
  69.             try  
  70.   
  71.             {  
  72.   
  73.                 connection();  
  74.   
  75.                 con.Open();  
  76.   
  77.                 //     return this.con.Query( query, param, null, true, null, commandType: CommandType.StoredProcedure).FirstOrDefault();  
  78.   
  79.                T Tlista = SqlMapper.Query<T>(con, query, param, nulltruenull, commandType: CommandType.StoredProcedure).FirstOrDefault();  
  80.   
  81.                 con.Close();  
  82.   
  83.                 return Tlista;  
  84.   
  85.             }  
  86.   
  87.             catch (Exception)  
  88.   
  89.             {  
  90.   
  91.                 throw;  
  92.   
  93.             }  
  94.   
  95.         }  
  96.   
  97.     }  
  98.   

In utilities folder, we will create a "Functions" class that contains a function that converts from IEnumerable to the datatable. This function serves to fill the grid controls.

  1. using System;  
  2.   
  3. using System.Collections.Generic;  
  4.   
  5. using System.Data;  
  6.   
  7. using System.Linq;  
  8.   
  9. using System.Text;  
  10.   
  11. using System.Threading.Tasks;  
  12.   
  13.   
  14. namespace DapperRepoWinForm.Utilities  
  15.   
  16. {  
  17.   
  18.     public class Funciones  
  19.   
  20.     {  
  21.   
  22.   
  23.         public DataTable ConvertToDataTable(IEnumerable<dynamic> items)  
  24.   
  25.         {  
  26.   
  27.             var t = new DataTable();  
  28.   
  29.             var first = (IDictionary<stringobject>)items.First();  
  30.   
  31.             foreach (var k in first.Keys)  
  32.   
  33.             {  
  34.   
  35.                 var c = t.Columns.Add(k);  
  36.   
  37.                 var val = first[k];  
  38.   
  39.                 if (val != null) c.DataType = val.GetType();  
  40.   
  41.             }  
  42.   
  43.   
  44.             foreach (var item in items)  
  45.   
  46.             {  
  47.   
  48.                 var r = t.NewRow();  
  49.   
  50.                 var i = (IDictionary<stringobject>)item;  
  51.   
  52.                 foreach (var k in i.Keys)  
  53.   
  54.                 {  
  55.   
  56.                     var val = i[k];  
  57.   
  58.                     if (val == null) val = DBNull.Value;  
  59.   
  60.                     r[k] = val;  
  61.   
  62.                 }  
  63.   
  64.                 t.Rows.Add(r);  
  65.   
  66.             }  
  67.   
  68.             return t;  
  69.   
  70.         }  
  71.   
  72.   
  73.     }  
  74.   

Now, we will create the folder ClassObjects. Inside the folder, we add a partial class "users".

  1. namespace DapperRepoWinForm.ClassObjects  
  2.   
  3. {  
  4.   
  5.     public partial class users  
  6.   
  7.     {  
  8.   
  9.         public string id { getset; }  
  10.   
  11.   
  12.         public string name { getset; }  
  13.   
  14.   
  15.         public string address { getset; }  
  16.   
  17.   
  18.         public string status { getset; }  
  19.   
  20.     }  
  21.   

The folder Bll is created and inside the folder, we add the class "usersBll". This class calls the processes stored, using the repository.

  1. using System;  
  2.   
  3. using System.Collections.Generic;  
  4.   
  5. using System.Linq;  
  6.   
  7. using System.Text;  
  8.   
  9. using System.Threading.Tasks;  
  10.   
  11. using DapperRepoWinForm.ClassObjects;  
  12.   
  13. using DapperRepoWinForm.Repository;  
  14.   
  15. using DapperRepoWinForm.Utilities;  
  16.   
  17. using Dapper;  
  18.   
  19.   
  20. namespace DapperRepoWinForm.Bll  
  21.   
  22. {  
  23.   
  24.     partial class users  
  25.   
  26.     {  
  27.   
  28.   
  29.         public string insertUpdate( ClassObjects.users _users)  
  30.   
  31.         {  
  32.   
  33.             RepGen  reposGen = new Repository.RepGen();  
  34.   
  35.             DynamicParameters param = new DynamicParameters();  
  36.   
  37.             param.Add("@id", _users.id);  
  38.   
  39.             param.Add("@name", _users.name);  
  40.   
  41.             param.Add("@address", _users.address);  
  42.   
  43.             param.Add("@status", _users.status);  
  44.   
  45.             return reposGen.executeNonQuery ("users_Insert_Update", param);  
  46.   
  47.         }  
  48.   
  49.   
  50.         public string delete(ClassObjects.users _users)  
  51.   
  52.         {  
  53.   
  54.             RepGen reposGen = new Repository.RepGen();  
  55.   
  56.             DynamicParameters param = new DynamicParameters();  
  57.   
  58.             param.Add("@id", _users.id);  
  59.   
  60.             return reposGen.executeNonQuery("users_DeleteRow_By_id", param);  
  61.   
  62.         }  
  63.   
  64.   
  65.         public List<ClassObjects.users> allRecords(ClassObjects.users  _usuario)  
  66.   
  67.         {  
  68.   
  69.             RepList<ClassObjects.users> lista = new RepList<ClassObjects.users>();  
  70.   
  71.             DynamicParameters param = new DynamicParameters();  
  72.   
  73.             return lista.returnListClass("users_SelectAll", param);  
  74.   
  75.   
  76.         }  
  77.   
  78.   
  79.         public List<ClassObjects.users> AllRecordsById(string id)  
  80.   
  81.         {  
  82.   
  83.             RepList<ClassObjects.users> lista = new RepList<ClassObjects.users>();  
  84.   
  85.             DynamicParameters param = new DynamicParameters();  
  86.   
  87.             param.Add("@id", id);  
  88.   
  89.             return lista.returnListClass("users_SelectRow_By_id", param);  
  90.   
  91.         }  
  92.   
  93.   
  94.         public ClassObjects.users findById(string id)  
  95.   
  96.         {  
  97.   
  98.             RepList<ClassObjects.users> class_usu = new RepList<ClassObjects.users>();  
  99.   
  100.             DynamicParameters param = new DynamicParameters();  
  101.   
  102.             param.Add("@Id", id);  
  103.   
  104.             return class_usu.returnClass("users_SelectRow_By_id", param);  
  105.   
  106.         }  
  107.   
  108.   
  109.         public List<dynamic> dynamicsList()  
  110.   
  111.         {  
  112.   
  113.             Funciones FG = new Funciones();  
  114.   
  115.             DynamicParameters param = new DynamicParameters();  
  116.   
  117.             Repository.RepList<dynamic> repo = new Repository.RepList<dynamic>();  
  118.   
  119.             var items = repo.returnListClass("users_SelectwithDate", param);  
  120.   
  121.             return items;  
  122.   
  123.         }  
  124.   
  125.   
  126.     }  
  127.   

Creating the XML file

Open a text editor and create a new file.

  1. <?xml version="1.0" encoding="utf-8" standalone="yes"?>  
  2. <Table>  
  3.   <Conexion>  
  4.     <Server>GP08</Server>  
  5.     <Database>DB_MVC</Database>  
  6.     <User>Admin2</User>  
  7.     <Password>123456</Password>  
  8.   </Conexion>  
  9.    
  10. </Table>   

Save it as conn.xml in "c:\”

This XML provides information for login and database to the project .

In the next article, I will explain how to use dapper in forms to execute the queries, search for the records and fill the grids.