.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:
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:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#