Esta vez aprovecho para contar como crear claves de varías columnas en NHibernate.

Hace ya un tiempo que estoy leyendo y practicando con este ORM, ya que es el ORM recomendado por el movimiento ALT.NET, y realmente es genial para desarrollos Domain Driven Development.

Lo que estoy haciendo es generando el schema de la DB a partir de la clase SchemaExport de NHibernate. Mediante esta clase genero los scripts DDL necesarios para crear el schema de la DB partiendo de los archivos .hbm de mapeo.

Realmente estoy más que conforme con esta herramienta por lo flexible y orientada a aplicaciones de mediana a grande complejidad.

Bueno vamos al motivo del post :)

En este caso tengo una tabla de aplicaciones y otra de usuarios. Un usuario pertenece a una aplicacion y su username no se puede repetir. Esto nos lleva a tener que crear en la tabla usuarios una unique constraint que tenga como columnas a ApplicationId y a Username. Esto lo podemos hace en el archivo de mapeo de NHibernate usando el elemento <column ../> hijo del elemento <property …/> y definiendo el atributo unique-key.

El archivo de mapeo quedaría como sigue:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="WPoch.Common.Providers.Membership"
                   namespace="WPoch.Common.Providers.Membership.Domain">
  <class name="User" table="`User`">
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Username">
      <column name="Username" unique-key="uq_User_Username"/>
    </property>
    <property name="Password"/>
    <property name="Comment"/>
    <property name="CreatedOn"/>
    <property name="Email"/>
    <property name="FailedPasswordAttempsCount"/>
    <property name="FailedPasswordAttempsWindowStart"/>
    <property name="IsAnonymous"/>
    <property name="IsApproved"/>
    <property name="IsLockedOut"/>
    <property name="LockedOutOn"/>
    <property name="LoggedOn"/>
    <property name="PasswordChangedOn"/>
    <many-to-one name="Application" cascade="all" not-null="true">
      <column name="ApplicationId" unique-key="uq_User_Username" />
    </many-to-one>
    <set name="Roles" lazy="true" cascade="all" table="UserRole">
      <key column="UserId" foreign-key="fk_UserRole_User" />
      <many-to-many class="Role" not-found="exception" column="RoleId"/>
    </set>
    <bag name="ProfileProperties" lazy="true" table="UserProfile">
      <key foreign-key="fk_UserProfile_User">
        <column name="UserId" unique-key="uq_UserProfile_Name"/>
      </key>
      <composite-element class="ProfileProperty">
        <parent name="User"/>
        <property name="Name" not-null="true">
          <column name="Name" unique-key="uq_UserProfile_Name"/>
        </property>
        <property name="ValueType" not-null="true" type="Type"/>
        <property name="ValueSerialized" type="StringClob"/>
        <property name="UpdatedOn" />
      </composite-element>
    </bag>
  </class>
</hibernate-mapping>

Como verán estoy desarrollando Membership, Role y Profile Providers de ASP.Net usando NHibernate de fondo, ya que lo que viene por defecto no es de mi agrado y acopla bien con los sistemas que estoy desarrollando.

Cuando tenga algo más avanzado, lo publicaré en la web.

Saludos,

Technorati Tags: