Quando estamos desenvolvendo sistemas concerteza vamos ter vários relacionamentos entre nossas entidades, um desses relacionamentos é um para muitos e nesse post vamos ver um exemplo de como fazer esse mapeamento usando o NHibernate.
Em nosso exemplo estaremos usando ASP NET MVC 2 com NHibernate 2 e banco de dados MySQL 5, vamos fazer um mapeamento de duas entidades Categoria e Produtos, onde uma Categoria possui vários Produtos, então mão no código. Se você não sabe como realizar a conexão com o NHibernate veja esse post Usando NHibernate com ASP NET MVC.
1) Criando as Entidades
Quando trabalhamos com o NHibernate temos que criar todas a propriedades (gets e sets) como virtual.
Categoria.cs
[sourcecode language=”csharp”]
public class Categoria
{
public virtual int IdCategoria { get; set; }
public virtual string Nome { get; set; }
public virtual string Descricao { get; set; }
public virtual IList<Produto> Produtos { get; set; }
}
[/sourcecode]
Veja que criamos uma propriedade do tipo IList que vai ter todos os produtos de uma determinada categoria.
Produto.cs
[sourcecode language=”csharp”]
public class Produto
{
public virtual int IdProduto { get; set; }
public virtual string Nome { get; set; }
public virtual string Descricao { get; set; }
public virtual Categoria Categoria { get; set; }
}
[/sourcecode]
2) Criando os Mapeamentos
Esses são os arquivos XML responsáveis pelo mapeamento das entidades.
Categoria.hbm.xml
Veja que criamos uma propriedade chamada BAG que será responsável por armazenar a nossa lista de produtos.
[sourcecode language=”xml”]
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ConexaoNHibernate.Entity"
namespace="ConexaoNHibernate.Entity" >
<class name="Categoria" table="tb_categoria">
<id name="IdCategoria" access="property" column="id_categoria" type="Int32">
<generator class="native"></generator>
</id>
<property name="Nome" not-null="true" access="property" type="String">
<column name="nome" length="100" />
</property>
<property name="Descricao" not-null="true" access="property" type="String">
<column name="descricao" length="100" />
</property>
<bag name="Produtos" cascade="save-update" lazy="true" >
<key column="id_categoria" />
<one-to-many class="Produto" />
</bag>
</class>
</hibernate-mapping>
[/sourcecode]
Produto.hbm.xml
Aqui temos uma propriedade Many to One onde definimos que um produto possui uma categoria.
[sourcecode language=”xml”]
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ConexaoNHibernate.Entity"
namespace="ConexaoNHibernate.Entity" >
<class name="Produto" table="tb_produto">
<id name="IdProduto" access="property" column="id_produto" type="Int32">
<generator class="native"></generator>
</id>
<property name="Nome" not-null="true" access="property" type="String">
<column name="nome" length="100" />
</property>
<property name="Descricao" not-null="true" access="property" type="String">
<column name="descricao" length="100" />
</property>
<many-to-one name="Categoria" column="id_categoria"
class="Categoria" not-null="true" />
</class>
</hibernate-mapping>
[/sourcecode]
OBS: Depois de criado os arquivos de mapeamento, não esqueça de alterar a propriedade Build Action para Embedded Resource
3) Testando
Vamos criar uma nova categoria, e depois criar os produtos dessa categoria e mandar salvar, veja abaixo o código:
[sourcecode language=”csharp”]
public ActionResult Create()
{
try
{
IList<Produto> lst = new List<Produto>();
ICategoryRepository categoryRepository = new CategoryRepository();
Categoria category = new Categoria();
category.Nome = "Comida";
category.Descricao = "Descrição da categoria comida";
category.Produtos = lst;
Produto product1 = new Produto();
product1.Nome = "Arroz";
product1.Descricao = "Descrição do produto arroz";
product1.Categoria = category;
lst.Add(product1);
Produto product2 = new Produto();
product2.Nome = "Feijão";
product2.Descricao = "Descrição do produto feijão";
product2.Categoria = category;
lst.Add(product2);
category = categoryRepository.Salvar(category);
return View();
}
catch (Exception ex)
{
log.Debug("ERRO", ex);
throw ex;
}
}
[/sourcecode]
Quando executamos o método Salvar passamos o objeto categoria com a lista de produtos, o NHibernate será responsável por realizar a manipulação nas tabelas necessárias.
Veja o resultado da execução no banco de dados
Qualquer dúvida, opinião, reclamação mande seu comentário!
Um Abraço!
Artigo bem fácil de entender. Valeu.
valeu @gabriel
Boa Noite! Estou com um problema num projeto muito simples.
Tenho uma tabela de cursos e outra de alunos
Curso: codcurso e descCurso
Aluno: CodAluno,NomeAluno e CodCurso.
Meu projeto é igual ao de cartegoria/ produto
Acontece que quando incluo um aluno e seleciono o codigo do curso numa combo, o nhibernate , alem de criar o aluno com um codigo de curso novo,an tabela aluno, cria também esse novo codigo de curso na tabela curso , em vez de gravar na tabela aluno o codigo do curso que eu selecionei através de uma combo.
Como faço para solucionar estre problema?
Rosangela,
Para você salvar essa relação entre Curso e Aluno, quando for salvar o curso você tem que carregar o curso em memória, mais ou menos assim
objAluno.curso = session.get(ID_DA_COMBO)
Depois de carregar o curso em memória você manda salvar o objeto aluno
Espero que ajude!
att,
Leandro Prado
Muito bom, simples e prático de se entender. Aguardo mais posts sobre NHIBERNATE, nos ajude a entender um pouco mais das grandes CRITERIAS =D
abraços!
Parabens
Valeu Saulo..
Estou programando uma série de posts com o Fluent NHibernate, em breve estará no ar!!!
att,
Leandro Prado
Parabéns, muito bom!