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.

8 comentarios en “Dapper Dot Net”

  1. Javier, buen post, hay muchos más micro-ORM como por ejemplo massive y/o otros. En realidad, esto no es muy nuevo, ya que es lo que haciamos muchos hacem muchos años y sufre de mucho de las cosas por las que algunos nos quisimos olvidar de esto, aunque lógicamente tiene su “escenario”, como casi toda la tecnología… Por ponerte algunas cosillas que merece la pena notar:

    * El que use IDbConnection no hace a Dapper multi-base de datos, porque el verdadero reto NO es basarse en la abstracción sino en que las queries sean compatibles, y esto, generalmente con este tipo de cosas solamente se consigue teniendo queries que NO aprovechen las capacidades de cada motor y por lo tanto queries lentas en todos..

    * La comparativa de velocidad, si te vas a fijar en la de Dapper vs EF está sesgada puesto en su comparación con EF, puesto que no han utilizado NoTracking, que lo haría mas justo. No obstante es más rápido… aunque no creo que puedan decir lo mismo dentro de unos meses 🙂

    Bueno, en realidad habría mucho más que hablar pero bueno, esta bien mostrar este tipo de cosas, mirate massive si te gustan los micro-orm

    saludos
    Unai

  2. Hola Unai,
    Lo primero gracias por comentar 🙂

    Estoy totalmente de acuerdo que la abstracción va a generar que no utilicemos realmente las capacidades de cada motor, pero para escenarios simples, donde vamos a tener consultas relativamente sencillas, no vamos a necesitar más 🙂

    Voy a preparar mas post acerca de Massive, PetaPoco y alguno más 😀

    Un saludo!

  3. Buen post! 🙂
    Sería interesante postearlo en los foros MSDN cada vez que alguien nombre los DataSets de los coj… esto… buen post! 🙂

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *