Archive for July 30, 2009

Mapeando subclases en varios archivos de NHibernate

Creando el mapping de una legacy DB en la oficina, me topé con el mapping de herencia de NHibernate (muy efectivo por cierto). Aunque ya he mapeado herencia anteriormente en NHibernate, algo que irrita de sobremanera es el archivo gigante que se crea ante la clase base. Revisando la documentación de NHibernate me topo con el concepto de mapas modulares para clases de herencia, algo que nos resuelve los dolores de cabeza con mapeos de herencia muy grandes :D

Tomemos por ejemplo este mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Sample"
                   namespace="Sample">
  <class name="Member" table="members">
    <id name="Username" column="username">
      <generator class="assigned" />
    </id>
    <discriminator column="type" type="Int32" />
    <property name="FirstName" column="first_name" not-null="true" />
    <property name="LastName" column="last_name" not-null="true" />
    <property name="Email" column="email" not-null="true" />
    <property name="BirthDate" column="birthdate" not-null="true" />
    <joined-subclass table="students" name="Student">
      <key column="student_id" />
            <property name="Added" />
    </joined-subclass>
  </class>
</hibernate-mapping>

(Para comprender un poco más de herencia en nhibernate usando joined-subclass recomiendohttp://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/inheritance.html en la documentación de NHibernate).

Bien, lo feo es que si he de mapear 5 clases heredadas debo agregar cada joined-subclass en el mismo archivo y eso me crearía archivos de mapeo poco portables y de díficil mantenimiento. Es cuando llega a salvar los archivos de mapeo modular.

En el caso anterior movemos la declaración de joined-subclass de Student a su propio archivo hbm y solo variamos agregandole el atributo “extends” indicando que clase (definida en su propio hbm) extendemos.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Sample"
                   namespace="Sample">
  <joined-subclass table="students" name="Student"
                   extends="Member">
    <key column="student_id" />
    <property name="Added" />
  </joined-subclass>
</hibernate-mapping>

Sencillo no?

Otro día hablaremos un poco más de nuestro siempre versátil NHibernate ;)

Cambiando el tamaño de una imagen con métodos de extensión

Es común en aplicaciones web trabajar con imágenes y hacer una que otra simple operación (cambiar el tamaño de una imagen, cambiar el formato de una imagen, obtener el MimeType de una imagen, cosas como esas).

Como duplicar código es lo peor que uno puede hacer, aproveché la simempre útili ayuda de los Extension Methods para estas simples operaciones, se los comparto a todos :D

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace Rioshu.Utils.Drawing
{
    public static class ImageExtensions
    {
        public static Image ToSize(this Image image, int width, int height)
        {
            var resized_image = new Bitmap(width, height);
            using (var graphics = Graphics.FromImage(resized_image)) {
                graphics.DrawImage(image, 0, 0, width, height);
            }

            return resized_image;
        }

        public static Image ToSize(this Image image, int size)
        {
            var max_side = image.Width > image.Height ? image.Width : image.Height;
            var factor = (float) size/max_side;

            var new_width = Convert.ToInt32(factor*image.Width);
            var new_height = Convert.ToInt32(factor*image.Height);

            return ToSize(image, new_width, new_height);
        }

        public static Image ToFormat(this Image image, ImageFormat format)
        {
            var memory_stream = new MemoryStream();
            image.Save(memory_stream, format);

            return new Bitmap(memory_stream);
        }

        public static byte[] GetBytes(this Image image)
        {
            var memory_stream = new MemoryStream();
            image.Save(memory_stream, image.RawFormat);
            var content = new byte[memory_stream.Length];
            memory_stream.Seek(0, SeekOrigin.Begin);
            memory_stream.Read(content, 0, content.Length);

            return content;
        }

        public static string GetMimeType(this Image image)
        {
            foreach (var codecInfo in ImageCodecInfo.GetImageDecoders()) {
                if (codecInfo.FormatID == image.RawFormat.Guid) {
                    return codecInfo.MimeType;
                }
            }
            return "image/unknown";
        }
    }
}

La forma de usarlos es sumamente fácil, basta con un simple ejemplo:

// digamos que leemos un archivo o stream que contiene una imagen
var image = Image.FromStream(file_stream).ToSize(125, 125);
// Resto de las operaciones de imagen

Espero le sea de ayuda a mas de alguien. Saludos!

Libro gratuito de PowerShell

Powershell es el super versátil y útil sucesor del infame Cmd en Windows. Este esta disponible para Windows XP, Windows 2003 Server, Windows Vista (como un download) e incluído en Windows 2008 Server. De hecho, Windows 7, Windows 2008 Server R2 y Windows Vista SP2 vendrán con PowerShell V2 el cuál incluye significantes cambios y mejoras en cuanto al poder disponible en la línea de comando.

Para aquellos que quieren comenzar a usar Powershell y explotarlo al máximo, Keith Hill (Powershell MVP) ha convertido su columna “Effective Powershell” en un libro gratuito descargable. Pueden bajarlo de aquí.

Saludos!

Comprimiendo el Response en ASP.NET MVC

Hace unos días escribí acerca de comprimir la salida del response en ASP.net Webfors usando el Global.asax, bien, hoy comparto con ustedes una forma simple y fácil de hacerlo en ASP.net MVC usando ActionFilters.

Simplemente creamos un ActionFilter como este:

using System.IO.Compression;
using System.Web;
using System.Web.Mvc;

namespace Rioshu.Examples
{
    public class CompressAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var request = filterContext.HttpContext.Request;
            var response = filterContext.HttpContext.Response;
            var encoding = request.Headers["Accept-Encoding"];
            if (string.IsNullOrEmpty(encoding))
            {
                return;
            }

            if (encoding.ToLowerInvariant().Contains("gzip"))
            {
                CompressGZip(response);
            }
        }

        static void CompressGZip(HttpResponseBase response)
        {
            response.AppendHeader("Content-Encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
    }
}

Y listo!. Para indicarle a nuestra “Acción” que debe comprimirse basta con “adornarla” con el atributo. Entonces sería algo así de sencillo:

using System.Web
using System.Web.Mvc

namespace Rioshu.Example
{
    public class Home
    {
        [Compress]
        public ActionResult Index()
        {
            return View();
        }
    }
}

Simple verdad!

Espero que esto les ayude en algo! Saludos!

Haciendo publish de un WebApplication en MSBuild