Blog de Francisco Velázquez

otro blog personal

DAOs sobre Dapper

leave a comment »

La verdad es que los micro-ORMs están de moda (Massive, Dapper, PetaPOCO, SimpleData, etc). Basándome en esta abstracción y en mi querido Gentle.NET, me he decido a construir unos DAOs sobre Dapper, que es usado en Stackoverflow, y como características principales podemos decir: que es fuertemente tipado con una interfaz muy clara, y como extra soporta operaciones asíncronas a DB.

Creo que la mejor manera de entender el funcionamiento es con un ejemplo:

    class Example
    {
        class Message
            : BusinessObject<Message>
        {
            [PrimaryKey]
            public Guid Id { get; set; }
            public string DestinationAddress { get; set; }
            public string SourceAddress { get; set; }
            public string UserData { get; set; }
            public int Ton { get; set; }

        }

        public void Example1()
        {
            Message m = new Message()
            {
                Id = Guid.NewGuid(),
                DestinationAddress = "34612345678",
                SourceAddress = "404",
                UserData = "Example 01",
                Ton = 1
            };

            m.Insert();

            List<Message> l = Message.FindBy(new SqlCondition("DestinationAddress", Operator.Equals, "34612345678"));

            m.Remove();
        }
    }

A continuación mostraremos el código de las funciones básicas de CRUD.

    public class BusinessObject<T>
        where T: class
    {
        public static SqlConnection GetConnection()
        {
            return ConnectionFactory.Create(typeof(T).Namespace);
        }

        public static T Retrieve(object id)
        {
            string sql = string.Empty;
            DynamicParameters p = new DynamicParameters();
            p.Add(GetPrimaryKey(), id, null, null, null);
            StringBuilder sb = new StringBuilder()
                .AppendFormat("select * from {0} where {1} = @{1}", GetTableName(), GetPrimaryKey());
            return queryInternal(sb.ToString(), p).FirstOrDefault();
        }

        public void Insert()
        {
            string sql = string.Empty;
            DynamicParameters p = new DynamicParameters();
            StringBuilder columns = new StringBuilder(), values = new StringBuilder();
            bool first = true;

            foreach (string prop in GetProperties())
            {
                if (first)
                {
                    columns.AppendFormat("{0}", prop);
                    values.AppendFormat("@{0}", prop);
                }
                else
                {
                    columns.AppendFormat(", {0}", prop);
                    values.AppendFormat(", @{0}", prop);
                }
                p.Add(prop, getPropertyValue(this, prop), null, null, null);
                first = false;
            }

            sql = string.Format("insert into {0} ({1}) values ({2})",
                GetTableName(), columns.ToString(), values.ToString());

            int res = executeInternal(sql, p);
        }

        public void Update()
        {
            // ... 
        }
        public void Remove()
        {
            // ...
        }

        public static List<T> FindBy(SqlCondition[] conditions)
        {
            DynamicParameters p = new DynamicParameters();
            StringBuilder sb = new StringBuilder()
                .AppendFormat("select * from {0} where", typeof(T).Name);

            bool first = true;
            int i = 0;
            foreach (SqlCondition c in conditions)
            {
                // for multiple conditions with same column
                string var = c.PropertyName + (i++);
                if (!first) sb.Append(" AND");

                if (c.Value == null)
                {
                    sb.AppendFormat(" {0} {1} NULL", c.PropertyName, OperatorHelper.ToString(c.Operator));
                }
                else
                {
                    sb.AppendFormat(" {0} {1} @{2}", c.PropertyName, OperatorHelper.ToString(c.Operator), var);
                    p.Add(var, c.Value, null, null, null);
                }
                first = false;
            }

            return queryInternal(sb.ToString(), p);
        }

        protected static List<T> queryInternal(string sql, object param)
        {
            List<T> l = null;

            using (var conn = GetConnection())
            {
                try
                {
                    conn.Open();
                    l = conn.Query<T>(sql, param, null, false, 0, null).ToList();
                }
                finally { conn.Close(); }
            }

            return l;
        }

Faltaría algo de código para representar las condiciones SQL, así como algunas funciones que usan reflección para optener el nombre de la tabla, propiedades o clave primaria.

Written by fravelgue

June 27, 2011 at 8:11 pm

Posted in development

Tagged with , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: