Dapper Dot Net
Introducción
Hace unos días Jorge Gamba comentaba en un twit algunos ORMS Ligeros para utilizar en algunos proyectos donde realmente no se requiere la potencia de Entity Framework o NHibernate. Esto venía a través de un intenso debate (y lucha) para intentar dejar a un lado los DataSets y DataTables que se utilizaban antiguamente.
¿Qué es Dapper?
Podríamos decir que Dapper es un mini-ORM (o un ORM Lite) compuesto por un conjunto de clases que nos van a permitir mapear nuestra base de datos con nuestras clases POCO.
Este “ORM” es independiente de la Base de Datos, puesto que hace uso de la interfaz IDbConnection, ya la mayoría de conexiones (SQL Server, Oracle, My SQL, OLEDB) tienen una Clase connection que implementa dicha interfaz.
¿Por donde empezar?
Para poder empezar a utilizar Dapper (no lo busquéis en Nuget, no está aún), tenéis que descargar un único fichero CS y agregarlo en vuestro proyecto de Visual Studio.
Algunos ejemplos
Vamos a ver algunos ejemplos muy sencillos de como utilizar Dapper, y ver la simplicidad de utilización que nos aporta:
Lo primero que vamos a hacer es declarar una variable conexión del tipo IDbConnection, para que podamos modificar el motor de Base de Datos de una forma muy rapida:
1: IDbConnection connection;
CONSULTA DE DATOS
El primer ejemplo lo voy a realizar sobre una Base de Datos SQL Server Express, y contra una tabla “Candidates” que voy a mapear a una clase como la siguiente:
1: public class CandidateInfo
2: {
3: public Guid CandidateId { get; set; }
4: public string CandidateName { get; set; }
5: public string CandidateLastName { get; set; }
6: public DateTime CandidateBirthDate { get; set; }
7: public byte[] CandidatePhoto { get; set; }
8: public int CandidateCountry { get; set; }
9: public int CandidateCity { get; set; }
10: public string CandidateEmail { get; set; }
11: }
Para obtener el conjunto de resultados de la tabla Candidates, ejecutariamos este bloque de código:
1: using (connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=MYCV;Integrated Security=True"))
2: {
3: connection.Open();
4: var Candidates = Dapper.SqlMapper.Query<CandidateInfo>(connection, "Select * From CandidateInfo");
5:
6: }
La Clase SqlMapper, está incluida en el fichero que hemos descargado. A través del método genérico Query se realiza el “mapeo” de la consulta que enviamos como parámetro al método.
Si en lugar de utilizar SQL Server estuviéramos usando cualquier otro tipo de BD, bastaría con modificar el bloque using y utilizar la clase de conexión del motor que tengamos.
El segundo ejemplo, va a ser para devolver un único tipo de dato simple:
1: using (connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=MYCV;Integrated Security=True"))
2: {
3: connection.Open();
4: var Candidates = Dapper.SqlMapper.Query<int>(connection, "Select CandidateCountry From CandidateInfo");
5: }
6:
En este caso vamos a obtener un conjunto de datos “int”.
A continuación, vamos a ver como utilizar parámetros:
1: using (connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=MYCV;Integrated Security=True"))
2: {
3: connection.Open();
4: var Candidates = Dapper.SqlMapper.Query<CandidateInfo>
5: (connection,
6: "Select * From CandidateInfo where CandidateLastName like @a",
7: new { a = "%Puertas%" });
8: }
El tercer parámetro del método Query, va a ser un array dinámico de Pares valor que se enlazarán a los parámetros de la query definida.
Ejemplo de consulta multiple, vamos a definir un conjunto de consultas contra el servidor y sus relativos Mapeos. Para este ejemplo vamos a hacer uso también de la siguiente clase:
1: public class CountryInfo
2: {
3: public int CountryID { get; set; }
4: public string CountryName { get; set; }
5: }
6:
El ejemplo consistirá en obtener la información de Candidates y Country:
1: using (connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=MYCV;Integrated Security=True"))
2: {
3: connection.Open();
4: var sql =
5: @"
6: select * from CandidateInfo
7: select * from CountryInfo";
8: using (var multi = Dapper.SqlMapper.QueryMultiple(connection, sql))
9: {
10: var candidates = multi.Read<CandidateInfo>().ToList();
11: var countries = multi.Read<CountryInfo>().ToList();
12: }
13: }
El método QueryMultiple se encargará de dividir las consulta SQL en varías, y el objeto GridReader existente en el fichero descargado se encargará de realizar los mapeos de cada una de las consultas a través del método genérico Read.
Por otro lado, también existe la posibilidad de utilizar procedimientos almacenados y mapearlo a las entidades de las que disponemos.
EJECUCIÓN DE SENTENCIAS
Una cosa que se encuentra en la cola de solicitudes / incidencias de Dapper, es que no tiene un método de inserción, actualización o borrado directo, pero se pueden ejecutar este tipo de sentencias de manera muy sencilla:
Ejemplo de Inserción simple:
1: using (connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=MYCV;Integrated Security=True"))
2: {
3: connection.Open();
4:
5: Dapper.SqlMapper.Execute(connection,
6: "INSERT INTO COUNTRYINFO (COUNTRYNAME) VALUES(@COUNTRY)",
7: new { COUNTRY = "Benin" });
8: }
Ejemplo de Inserción múltiple (va a ejecutar la misma sentencia, cambiando los valores de los parámetros según la lista de valores que dispongamos):
1: using (connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=MYCV;Integrated Security=True"))
2: {
3: connection.Open();
4:
5: var lista = new List<dynamic>();
6: lista.Add(new { COUNTRY = "Italia" });
7: lista.Add(new { COUNTRY = "Francia" });
8: lista.Add(new { COUNTRY = "Alemania" });
9: Dapper.SqlMapper.Execute(connection, "INSERT INTO COUNTRYINFO (COUNTRYNAME) VALUES(@COUNTRY)",
10: lista);
11: }
Existe la posibilidad de hacer uso de transacciones (IDbTransaction) a la hora de ejecutar las sentencias, ya que el método Execute dispone de un parámetro opcional que la puede administrar, pero para hacer la confirmación (“Commit”) sería necesario ejecutarlo después de la ejecución.
Conclusiones
Dapper presenta algunas funcionalidades curiosas y unos tiempos (que veremos en una futura comparativa que voy a publicar) bastante interesantes, y que habría que tenerlo en cuenta, tal como decía al principio, si no necesitamos la potencia de algo mas grande.
Voy a realizar el análisis de otras herramientas similares a Dapper y al final publicaré una comparativa sobre tiempos.