Usando ConfORM para mapear NHibernate 2da vuelta

Tomando como base el primer post que hice de ConfORM voy a agregar algunas cosas más.

Al dominio que ya habíamos visto le agrego la clase CalculoDePrecios que es un Servicio (Service en el sentido de DDD) solo para que haya una clase en el dominio que no voy a persistir.

Diagrama de Clases
Hace click para ver la imagen más grande

Por otro lado la vez anterior no usé la dll Conform.Shop que ahora si voy a incluir.

El código para mapear mi dominio me queda ahora así:

            var orm = new ObjectRelationalMapper();
            orm.TablePerClass(typeof(Producto).Assembly.GetTypes().Where(t => typeof(Entidad).IsAssignableFrom(t)));
            orm.Exclude<Entidad>();
            orm.Cascade<Orden, LineaOrden>(Cascade.All | Cascade.DeleteOrphans);
            // hay que especificar las relaciones Many to Many
            orm.ManyToMany<Producto, Etiqueta>();
            // hay que especificar las relaciones One to One
            orm.OneToOne<Producto, Imagen>();

            IPatternsAppliersHolder patternsAppliers = new SafePropertyAccessorPack().Merge(new CoolColumnsNamingPack(orm));
            Mapper mapper = new Mapper(orm, patternsAppliers);
            mapper.Customize<Producto>(c => c.Property(p => p.codigo, m => { m.Length(10); m.NotNullable(true); m.Unique(true); }));

            Type type = typeof(Producto);
            HbmMapping mapping = mapper.CompileMappingFor(type.Assembly.GetTypes());

            Configuration cfg = new Configuration();
            // tomo la configuración del archivo hibernate.cfg.xml
            cfg.Configure();
            cfg.AddDeserializedMapping(mapping, "FullDomain");

Este código de mapeo me genera estas tablas:

Diagrama de tablas
Hace click en la imagen para ver una versión más grande

Las diferencias con el primer post son:

            orm.TablePerClass(typeof(Producto).Assembly.GetTypes().Where(t => typeof(Entidad).IsAssignableFrom(t)));
            orm.Exclude<Entidad>();

En vez de usar TablePerConcreteClass uso TablePerClass y excluyo explícitamente Entidad porque no quiero tener un tabla para esa clase. Para mi dominio no hay diferencia pero con esto muestro como se puede excluir una clase.

            orm.Cascade<Orden, LineaOrden>(Cascade.All | Cascade.DeleteOrphans);

En términos de DDD, Orden y LineaOrden forman un Aggregate en el que Orden es el Aggregate Root, dicho de otra forma LineaOrden está ligado al ciclo de vida de Orden y sólo se concibe su existencia como hijo de Orden, al guardar Orden se guardan sus lineas y al borrar la Orden se borran sus lineas, para eso uso Cascade.

            IPatternsAppliersHolder patternsAppliers = new SafePropertyAccessorPack().Merge(new CoolColumnsNamingPack(orm));
            Mapper mapper = new Mapper(orm, patternsAppliers);

La clase CoolColumnsNamingPack es un clase que engloba varios “pattern appliers” que son patrones (o convenciones) y en este caso me sirven para que ConfORM me genere mejores nombres para las columnas. Por ejemplo para la tabla many to many de Productos y Etiquetas me genera ProductoId y EtiquetaId como columnas, cosa que no pasaría si no usara este pack .

Hay muchos pattern appliers y packs para nombres de columnas, nombres de tablas y otros patrones en Conform.Shop.

Una característica interesante de esto es el uso junto con los “Inflectors”. Por ejemplo:

            var inflector = new SpanishInflector();
            IPatternsAppliersHolder patternsAppliers = new ConfOrm.Shop.InflectorNaming.PluralizedTablesPack(orm, inflector);

Esto me generaría tablas con nombres en plural y como le paso el SpanishInflector usará las reglas del castellano para llevar el nombre de la clase al plural.

Está también disponible el ItalianInflector para italiano y sino por defecto usa el inglés.

Por último 2 links:
– Alessandro Giorgetti creo una herramienta muy buena para trabajar con ConfORM, que nos permite ver los mappings y el script de SQL, se llama Conform ToolBox Mapping Explorer.

– un proyecto de ejemplo del uso de ConfORM + NHibernate hecho por Fabio Maulo: https://bitbucket.org/fabiomaulo/nhmystic/overview

var orm = new ObjectRelationalMapper();
orm.TablePerClass(typeof(Producto).Assembly.GetTypes().Where(t => typeof(Entidad).IsAssignableFrom(t)));
//orm.TablePerConcreteClass<Producto>();
//orm.TablePerClassHierarchy<Producto>();// NO uses Identity !! Esto es solo para que sepas como usar otro POID Generator 🙂
//orm.Patterns.PoidStrategies.Add(new ConfOrm.Patterns.IdentityPoidPattern());

// Orden y LineaOrden son un Aggregate por ende no habrá un repositorio de LineaOrden
// así que quiero que se persista y borre automáticamente con Orden por eso el Cascade
orm.Cascade<Orden, LineaOrden>(Cascade.All | Cascade.DeleteOrphans);

// No quiero tener un tabla Entidad
orm.Exclude<Entidad>();

// hay que especificar las relaciones Many to Many
orm.ManyToMany<Producto, Etiqueta>();

// hay que especificar las relaciones One to One
// marcarlo con OneToOne me genera el cascade y un Unique Key para imagen en la tabla Producto
orm.OneToOne<Producto, Imagen>();

// puedo usar inflectors y el PluralizedTablesPack para generar tablas con nombres en plural
// están disponibles inflectors para Español, Italiano e Inglés (default)
//var inflector = new SpanishInflector();
//var inflector = new ItalianInflector();
//IPatternsAppliersHolder patternsAppliers = new ConfOrm.Shop.InflectorNaming.PluralizedTablesPack(orm, inflector);

// Con el Pack de Cool Columns Naming me genera mejores nombres a las columnas
// mirar por ejemplo la diferencia en los nombres de las columnas de las tablas many to many
// hay un montón de appliers y packs (conjunto de appliers) fijate en Conform.Shop
IPatternsAppliersHolder patternsAppliers = new SafePropertyAccessorPack().Merge(new CoolColumnsNamingPack(orm));

Mapper mapper = new Mapper(orm, patternsAppliers);
mapper.Customize<Producto>(c => c.Property(p => p.codigo, m => { m.Length(10); m.NotNullable(true); m.Unique(true); }));

Type type = typeof(Producto);
HbmMapping mapping = mapper.CompileMappingFor(type.Assembly.GetTypes());

Anuncios

3 comentarios en “Usando ConfORM para mapear NHibernate 2da vuelta

  1. So queres usar Packs-composition fijate en usage-examples y verás que podes sacar tambien Cascade ya que ConfORM va a descubrir la bidirectional-one-to-many solito y va a aplicar mapping-pattern correspondiente.
    Ho http://bitbucket.org/ parece que no anda, cuando vuela busca con mi nombre y apellido y va a encontrar NHibernateMystic, allí tenes un pack composition bastante completo.

    1. Fabio, muchas gracias por estos datos (y por ConfORM!), sigo aprendiendo y descubriendo nuevas features. También ya lo estoy usando en un proyecto en producción con excelentes resultados.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s