No NHibernate existem três formas de fazer o mapeamento entre suas classes de domínio e suas tabelas relacionais, são elas:
- Arquivos XML;
- Atributos (Anotações);
- Mapeamento Fluente;
Vou explicar como fazer o mapeamento usando cada uma destas opções bem como apontar as vantagens e desvantagens de cada uma delas.
1. Arquivos XML
Este é o mais comun pois se trata da forma mais antiga de se fazer o mapeamento. Como o NHibernate surgiu do Hibernate (Java), e em Java era muito comum utilizar arquivos XML para fazer configurações (ainda é comum), foi assim que o NHibernate começou também. Nesta opção nós temos um arquivo XML para cada entidade. Veja este exemplo.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="MyApplication.Domain.Customer, MyApplication.Domain" lazy="true">
<id name="Id">
<generator class="identity" />
</id>
<property name="FirstName" type="String" column ="FirstName" length="40" not-null="true" />
<property name="LastName" type="String" column="LastName" length="100" not-null="true" />
<property name="Birthday" type="DateTime" column="Birthday" not-null="false" />
</class>
</hibernate-mapping>
E a entidade ficaria assim.
public class Customer
{
public virtual int ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual DateTime Birthday { get; set; }
}
Simples assim, não tem muito segredo.
- Vantagens
- É o mais maduro pois já está a bastante tempo em uso;
- Desvantagens
- Configuração complicada;
- É necessário lembrar de compilar junto com os Assemblies;
- Está muito propício ao erro, se alterar a entidade precisa lembrar de alterar o mapeamento;
2. Atributos (Anotações)
Atributo é o nome dado às classes em C# que são usadas para decorar propriedades ou métodos. É equivalente à anotação em Java. Nesta opção agora não temos mais arquivos externos, todo o mapeamento é feito na própria classe. Olha só um exemplo do mesmo mapeamento que fizemos acima.
[Class]
public class Customer
{
[Id(Name = "Id")]
[Generator(1, Class = "Identity")]
public virtual int ID { get; set; }
[Property(Name="FirstName", NotNull = true, Length = 40)]
public virtual string FirstName { get; set; }
[Property(Name="LastName", NotNull = true, Length = 100)]
public virtual string LastName { get; set; }
[Property(Name="Birthday", NotNull = false, )]
public virtual DateTime Birthday { get; set; }
}
- Vantagens
- Compilação facilitada;
- Alteração fica centralizada em apenas um lugar;
- Desvantagens
- Poluição da classe, começa a ter mais linhas, fica menos legível e cria uma forte dependência com o NHibernate;
3. Mapeamento Fluente
Este é a mais nova opção de mapeamento e apenas disponível para .Net. Trata-se de uma combinação do melhor de cada um dos modelos acima. Olha como fica.
public class Customer
{
public virtual int ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual DateTime Birthday { get; set; }
}
Veja que minha entidade não mudou nada com relação ao primeiro exemplo.
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.Id);
Map(x => x.FirstName).Length(40).Not.Nullable();
Map(x => x.LastName).Length(100).Not.Nullable();
Map(x => x.Birthday).Nullable();
}
}
Agora sim chegamos numa solução que eu chamaria de perfeita. Para saber mais sobre o Fluent NHibernate acesse o site oficial.
- Vantagens
- Compilação facilitada;
- Classes pequenas, simples e limpas;
- Desvantagens
- Este framework é bem novo quando comparado com os outros dois, por isso pode apresentar alguns defeitos. Entretanto, até agora nunca tive problemas.
Fico pensando se existe alguma outra forma de realizar os mapeamentos. Me parecem que todas elas já foram exploradas. Acho que ficou claro que eu gosto bastante do Fluent NHibernate, e você?
Legal. Hoje usar o NHibernate + Fluent NHibernate é de longe é a melhor solução. Lembrando também que você pode fazer a configuração(dialect, driver, connectiostring) através da biblioteca.
Bem lembrado mesmo. Com o Fluent NHibernate você tem um resultado 100% non-XML. E a configuração continua sendo fácil, usando as técnicas de interface fluente.
como faço mapeamento “Fluent” quando existem tabelas mestre-detalhe?
Venda->Itens por exemplo
A forma mais simplista é usar:
HasMany<ItemDePedido>(x => x.Itens);
Se precisar especificar nome de coluna ou opções avançadas como lazyload ou cascade, você pode ir utilizando os métodos adicionais, algo assim:
HasMany<ItemDePedido>(x => x.Itens).LazyLoad().Cascade.All();