.NET -  Fluent NHibernate e Fluent Mapping


Fluent Mapping ou mapeamento fluente é o estilo de mapeamento que o Fluent NHibernate utiliza. Ele é uma interface fluente que permite que você mapeie as suas entidades via código com toda a segurança do tempo de compilação. 

Na seção  NHibernate - Macoratti.net você vai encontrar muitos artigos que eu já escrevi mostrando como usar os recursos do NHibernate.

Nota:  Para saber mais sobre interface fluente veja o link: http://martinfowler.com/bliki/FluentInterface.html

Se você já chegou a usar o NHibernate e não conhece o Fluent NHibernate deve saber que gerar os arquivos de mapeamento (.hbm) dá muito trabalho e que é uma tarefa  que esta sujeita a erros.

Pois se esse isso era um quesito que o desmotivava a usar o NHibernate fique sabendo que agora você não tem mais essa desculpa.

O Fluent NHibernate chegou (a um bom tempo por sinal) para auxiliar a realização dos mapeamentos das suas entidades com o seu banco de dados. Com ele podemos realizar o mapeamento via código sem ter que usar os arquivos .hbm.

Apenas para comparar veja abaixo um exemplo de um arquivo de mapeamento .hbm gerado e sua contrapartida usando o Fluent NHibernate:       

(fonte: https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started)

<?xml version="1.0" encoding="utf-8" ?>  
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  
  namespace="QuickStart" assembly="QuickStart">  
  <class name="Cat" table="Cat">  
    <id name="Id">  
      <generator class="identity" />  
    </id>  
    <property name="Name">  
      <column name="Name" length="16" not-null="true" />  
    </property>  
    <property name="Sex" />  
    <many-to-one name="Mate" />  
    <bag name="Kittens">  
      <key column="mother_id" />  
      <one-to-many class="Cat" />  
    </bag>  
  </class>  
</hibernate-mapping>

 

public class CatMap : ClassMap<Cat>
{
  public CatMap()
  {
    Id(x => x.Id);
    Map(x => x.Name)
      .Length(16)
      .Not.Nullable();
    Map(x => x.Sex);
    References(x => x.Mate);
    HasMany(x => x.Kittens);
  }
}

 

Arquivo XML .hbm código Fluent NHibernate equivalente

O Fluent NHibernate pode ser baixado no seguinte link:  http://www.fluentnhibernate.org/

Neste artigo eu vou apresenta alguns conceitos básicos necessários para realizar o mapeamento usando o Fluent NHibernate.

Recursos usados

Objetivos

Fluent Mapping

O Fluent NHibernate também possui várias outras ferramentas, incluindo:

O Fluent NHibernate é externo ao núcleo do NHibernate, mas é compatível com as versões do NHibernate. A seguir veremos alguns recurso básicos usados para realizar o mapeamento fluente com o Fluent NHibernate.

A classe ClassMap<T>

A classe ClassMap<T> é a base de todo o mapeamento feito pelo Fluent NHibernate, precisamos herdar dessa classe para realizar o mapeamento.

Ao iniciar qualquer mapeamento com o Fluent NHibernate você deve ter em mente 3 regras básicas:

  1. Para cada entidade devemos ter uma classe Map (Ex: Pessoa -> PessoaMap);
  2. As classe Map devem herdar da ClassMap;
  3. A definição do mapeamento deve ser inserida no construtor da classe Map;

Abaixo vemos um trecho de código que inicia mapeamento de uma classe Pessoa:

public class PessoaMap : ClassMap<Pessoa>
{
  public PessoaMap()
  {
  }
}
Public Class PessoaMap
	Inherits ClassMap(Of Pessoa)

	Public Sub New()
	End Sub
End Class
C# VB .NET

É no construtor da classe que mapeamos as várias propriedades das entidades.

Cada mapeamento dentro de um ClassMap <T> é construído usando expressões lambda, o que nos permite fazer referência às propriedades de suas entidades sem sacrificar o tempo de compilação de segurança.

As lambdas geralmente tomam a forma de x => x.Property (C#) e Function(x) m.Property  (VB .NET) ; onde o x do lado esquerdo é a declaração de parâmetro, que será a entidade que você está mapeando, enquanto o x.Property está acessando uma propriedade em sua entidade.

Depois de ter declarado sua ClassMap <T> você precisa mapear as propriedades em sua entidade. Existem vários métodos disponíveis que mapeiam as propriedades de formas diferentes, e cada uma delas é uma cadeia de método que você pode usar para personalizar o mapeamento individual.

O Método Id

Cada mapeamento requer um Id de algum tipo, estes são mapeados usando o método de Id; este método tem uma expressão lambda da propriedade que você deseja usar como seu ID.

Dependendo do tipo de retorno da propriedade que você fornecer, o Fluent NHibernate irá fazer algumas suposições sobre o tipo de identificador que você está usando. Por exemplo, se sua propriedade ID é um int, então vamos supor que você está usando uma coluna de identidade; Da mesma forma, se você usar um Guid então assumimos que é um valor Guid.

Id (x => x.Id);
 Id(Function(x) x.Id)
C# VB .NET

Esse é o cenário mais comum para mapear seu Id. As personalizações podem ser feitas pelo encadeamento de métodos fora da chamada de Id. Por exemplo, se tivéssemos que mudar qual coluna mapeia a propriedade para que pudéssemos usar o método de coluna, ou para especificar explicitamente o gerador de identidade você pode usar a propriedade GeneratedBy.

Id (x => x.Id).Column ("PessoaId").GeneratedBy.Assigned();
 Id(Function(x) x.Id).Column("PessoaId").GeneratedBy.Assigned()
C# VB .NET
Neste exemplo estamos especificando que a propriedade Id é mapeada para uma coluna PessoaId no banco de dados, e está usando um gerador atribuído.
Mapeando Propriedades
O mapeamento de propriedades se constitui numa grande quantidade de qualquer domínio mapeado e elas são simples de mapear como as identidades, basta usar o método Map:
Map (x => x.Nome);
 Map(Function(x) x.Nome)
C# VB .NET

Isso é tudo que você precisa para a maioria das situações. O Fluent NHibernate sabe qual o tipo de retorno de sua propriedade, e assume que a coluna é o mapeamento para a qual ele esta mapeando terá o mesmo nome que a propriedade.

Existem inúmeras personalizações disponíveis através de métodos encadeados a partir da chamada do método Map. Por exemplo, se você está gerando o seu esquema você pode querer especificar se a própria coluna é anulável, você pode fazer isso usando o método anulável e (opcionalmente) a propriedade operador Not.

// anulável
Map(x => x.Nome).Nullable ();

// Não anulável
Map(x => x.Nome).Not.Nullable();
 // anulável
Map(Function(x)  x.Nome).Nullable ();

// Não anulável
Map(Function(x)  x.Nome).Not.Nullable();
C# VB .NET

Mapeando Relacionamentos

A não ser para os domínios mais básicos é quase certo que você terá que realizar o mapeamento de relacionamentos entre as entidades.

Os relacionamentos mais comuns são os do tipo muitos-para-um, um-para-muitos e muitos-para-muitos, sendo que eles são referidos no contexto do Fluent NHibernate como referências HasMany´s e HasManyToMany´s.

1-) References / muitos-para-um (Many-to-one)

O método References é usado para criar uma referência com outra entidade.

Vejamos um exemplo de relacionamento muitos-para-um que ocorre entre uma entidade Pessoa e uma entidade Autor.

Pensando em termos de entidades podemos ter :

public class Endereco
   public Pessoa Pessoa {get; set; }
}
Public Class Endereco
    Public Property Pessoa() As Pessoa
End Class
C# VB .NET

Para definir este relacionamento podemos usar o seguinte código no construtor da classe:

public class EnderecoMap : ClassMap<Endereco>
{
  public EnderecoMap()
  {
    ....
    References(x=>x.Pessoa);
  }
}
Public Class EnderecoMap
	Inherits ClassMap(Of Endereco)

	Public Sub New()
              ...
              References(Function(x) x.Pessoa)                            
	End Sub
End Class
C# VB .NET

Com esse código criamos uma relação entre as referências do livro e do autor. A chave estrangeira é assumida como sendo Author_id na tabela Livro, mas você pode mudar isso usando método Column.

Tal como acontece com todos os outros mapeamentos fluentes, você pode encadear chamadas para personalizar a relação de referência. Por exemplo, se você quiser especificar a estratégia em cascata você pode usar a propriedade Cascade:

References (x => x.Autor).Column ("AutorID").Cascade.All();
References (Function(x)  x.Autor).Column ("AutorID").Cascade.All();
C# VB .NET

2-) HasMany / um-para-muitos (one-to-many)

HasMany é provavelmente o relacionamento mais comum baseada em coleção.

O HasMany é o "outro lado" de uma relação de referências.

Usando o mesmo exemplo acima, desta vez vamos mapear lado do autor que se junta na tabela Livros retornando uma coleção de todos os livros desse autor.

public class Autor
{
   public IList <Book> Livros {get; set; }
}
Public Class Autor
      Public Property Livros() As IList(Of Livro)
End Class
C# VB .NET

Para mapear isso, usamos o método HasMany, assim:

HasMany (x => x.Livros);
HasMany (Function(x)  x.Livros);
C# VB .NET

Definimos que a entidade Autor tem uma referência de um-para-muitos com a entidade Livros.

Tal como acontece com References, a chave estrangeira é definida como autor_id, e você pode substituí-la com o método KeyColumn.

Existem alguns tipos diferentes de coleções que você pode usar, e eles estão todos disponíveis no âmbito da chamada HasMany.

3-) HasManyToMany / muitos-para-muitos (many-to-may)

HasManyToMany funciona exatamente da forma que HasMany/one-to-many, exceto a a estrutura do banco de dados subjacente que ele mapeia é diferente.

Vejamos um exemplo de mapeamento entre as entidade Autor e Livro onde temos um relacionamento muitos-para-muitos:

public class Autor
{
   public virtual int Id { get; set; }
   public virtual string Nome { get; set; }
  public virtual IList<Livro> Livros { get; set; }
}
Public Class Autor
  Public Overridable Property Id() As Integer
  Public Overridable Property Nome() As String
  Public Overridable Property Livros() As IList(Of Livro)
End Class
public class Livro
{
  public virtual int Id { get; set; }
  public virtual string Nome { get; set; }
  public virtual IList<Autor> Autores { get; set; }
}
Public Class Livro
  Public Overridable Property Id() As Integer
  Public Overridable Property Nome() As String
  Public Overridable Property Autores() As IList(Of Autor)
End Class
C# VB .NET

O mapeamento pode ser feito da seguinte forma:

HasManyToMany (x => x.Livros);
HasManyToMany (Function(x)  x.Livros);
C# VB .NET

Existem alguns tipos diferentes de coleções que você pode usar, e eles estão todos disponíveis no âmbito da chamada HasManyToMany.

Esses conceitos são suficientes para você iniciar o mapeamento de suas entidades existem outros recursos que podem ser usados para casos mais complexos e para detalhar o mapeamento.

Você pode consultar o site oficial do Fluent NHibernate, e no link https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started você encontra um exemplo básico que mostra os principais mapeamentos em um exemplo prático.

João 3:17 Porque Deus enviou o seu Filho ao mundo, não para que julgasse o mundo, mas para que o mundo fosse salvo por ele.

João 3:18 Quem crê nele não é julgado; mas quem não crê, já está julgado; porquanto não crê no nome do unigênito Filho de Deus.

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

 

             Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter
 

Referências:


José Carlos Macoratti