;

terça-feira, 18 de janeiro de 2011

Usando NHibernate - Parte I

Hoje começo uma série de artigos nos quais abordarei o uso de NHibernate. Neste primeiro artigo falarei um pouco sobre este framework e irei apresentar um exemplo simples de inserção e consulta de dados.

O que é NHibernate

NHibernate é um framework para a persistência de dados de objetos  .NET para bases de dados relacionais. É baseado no Hibernate do Java, sendo muito utilizado por desenvolvedores desta plataforma.

O NHibernate implementa os métodos CRUD (create, read, update e delete) para as classes mapeadas. Desta maneira o desenvolvedor não precisa implementar tais métodos, tampouco precisa se preocupar em validar os dados, pois o NHibernate já os trata corretamente.

Preparando o ambiente

Para o exemplo que apresentarei neste artigo utilizei a versão 2.0.1.GA. O NHibernate já está em sua versão 3.0, que possui alguns recursos a mais. Utilizei esta versão porque atende perfeitamente as necessidades deste exemplo. Além disto, acredito que ainda seja a versão mais utilizada. Porém, se preferir utilizar outra versão, recomendo ler a documentação do framework, para ver como proceder com os arquivos de configuração e mapeamento. O banco de dados utilizado neste exemplo é SQL Server Express 2008. 

Para começar, baixe a biblioteca do NHibernate e descompacte os arquivos.  Em seguida crie uma base de dados e insira uma tabela chamada “Cliente”. Esta tabela deve ter os campos:

- codigo: tipo Int. É a primary key da tabela;
- nome: Tipo varchar de tamanho 50.

Tabela Cliente


Terminado o banco, crie uma aplicação Windows Forms no Visual Studio.
Criar aplicação Windows forms
 
Na solution explorer adicione as dlls do NHibernate, encontradas no pacote baixado. Para a versão utilizada neste exercício são necessários os arquivos Castle.Core.dll, Iesi.Collections.dll, log4net.dll, NHibernate.dll e Castle.DynamicProxy2.dll.

Inclua também um form e neste coloque dois TextBoxes, um botão e um DataGridView, conforme  a imagem abaixo:
Form de cadastro

Agora crie uma classe Cliente, da seguinte maneira:

namespace Cadastro
{
    class Cliente
    {
        public int Codigo { get; set; }
        public string Nome { get; set; }
    }
}

Agora é necessário criar o mapeamento da classe, para que o NHibernate saiba em qual tabela persistir os dados desta classe. Adicione um arquivo texto no projeto e renomeie para “Cliente.hbm.xml”. Inclua o código abaixo no arquivo e salve. Após salvar, altere a propriedade Build Action do arquivo para Embedded Resource.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Cadastro.Cliente, Cadastro" table="Cliente" lazy="false">
    <id name="Codigo" column="codigo" type="Int32">
      <generator class="assigned" />
    </id>
    <property name="Nome" column="Nome" type="String" length="50" />
  </class>
</hibernate-mapping>

Para concluir o mapeamento, crie um arquivo app.config com o seguinte código:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="hibernate-configuration"
    type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"/>
  </configSections>
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">
        NHibernate.Connection.DriverConnectionProvider
      </property>
      <property name="dialect">
        NHibernate.Dialect.MsSql2005Dialect
      </property>
      <property name="connection.driver_class">
        NHibernate.Driver.SqlClientDriver
      </property>
      <property name="connection.connection_string">
        Data Source=.\SQLEXPRESS;Integrated Security=True; initial catalog=nhibernate
      </property>
    </session-factory>
  </hibernate-configuration>
</configuration>

Pronto, agora já podemos criar os métodos de inserção e consulta de dados.

Inserindo registros

Para a inserção de registros, no form criado para a entrada de dados, crie um método que trate o evento click do botão. Neste método insira o código apresentado a seguir.

private void Salvar_Click(object sender, EventArgs e)
{
    try
    {
        Configuration cnfg = new Configuration();

        //Assembly dos arquivo .hbm.xml
        cnfg.AddAssembly("Cadastro");
       
        cnfg.SetProperty("hibernate.dialect", "NHibernate.Dialect.MsSql2005Dialect");

        //criação de uma sessao
        ISessionFactory oFactory = cnfg.BuildSessionFactory();
        ISession oSession = oFactory.OpenSession();
        //iniciando uma transação
        ITransaction oTransaction = oSession.BeginTransaction();

        Cliente objCliente = new Cliente();
        objCliente.Nome = nome.Text;
        objCliente.Codigo = int.Parse(codigo.Text);

        //persistindo o objeto no banco de dados
        oSession.Save(objCliente);
        //Fecha a transaçao
        oTransaction.Commit();
        oSession.Close();

        carregaDados();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Como podemos ver, é necessário apenas instanciar um objeto da classe Cliente e os objetos do NHibernate. O Framework se encarrega de inserir os dados no banco de dados, na tabela mapeada para o objeto da classe, passada no método Save.

Ao final deste método temos uma chamada do método carregaDados(). Este é responsável por carregar o grid que temos no form da aplicação. Também é chamado no Load do form, para carregar os dados ao abrir a aplicação.

Consultando os dados

O NHibernate, naturalmente, oferece métodos para a recuperar um objeto a partir de sua chave primária. Assim como também é possível carregar uma lista de objetos. O método carregaDados() usado para popular o grid fica da seguinte forma:

private void carregaDados()
{
    Configuration cnfg = new Configuration();

    //Assembly dos arquivo .hbm.xml
    cnfg.AddAssembly("Cadastro");
    //seta o dialeto do banco de dados
    cnfg.SetProperty("hibernate.dialect", "NHibernate.Dialect.MsSql2005Dialect");

    //criação de uma sessao
    ISessionFactory oFactory = cnfg.BuildSessionFactory();
    ISession oSession = oFactory.OpenSession();
    //iniciando uma transação
    ITransaction oTransaction = oSession.BeginTransaction();

    IList clientes = oSession.CreateCriteria(typeof(Cliente)).List();

    grid.Rows.Clear();

    foreach (Cliente cli in clientes)

        grid.Rows.Add(cli.Codigo, cli.Nome);

    oSession.Close();
}

Repare que temos um objeto Colection.Ilist para receber o retorno do método CreateCriteria(), que é o método que retorna a lista de objetos solicitada. Com esta lista populamos o grid.
 
Para consultar os dados de um dos registros, crie um método para tratar o evento CellDoubleClick do datagridview, e insira o código, conforme mostrado  a seguir:

private void grid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
    try
    {
        Configuration cnfg = new Configuration();

        //Assembly dos arquivo .hbm.xml
        cnfg.AddAssembly("Cadastro");
        //seta o dialeto do banco de dados
        cnfg.SetProperty("hibernate.dialect", "NHibernate.Dialect.MsSql2005Dialect");

        //criação de uma sessao
        ISessionFactory oFactory = cnfg.BuildSessionFactory();
        ISession oSession = oFactory.OpenSession();
        //iniciando uma transação
        ITransaction oTransaction = oSession.BeginTransaction();

        Cliente cli = (Cliente)oSession.Load(typeof(Cliente), grid.SelectedRows[0].Cells[0].Value);

        MessageBox.Show(cli.Codigo + " - " + cli.Nome);
        oSession.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Este método passa para o NHibernate o código do objeto selecionado, que retorna, através do método Load, o objeto solicitado, exibindo as informações em uma messagebox.

No próximo artigo continuaremos falando do NHibernate, abordando outros métodos e funcionalidade deste framework.

4 comentários:

Unknown disse...

gostaria de saber como consigo mapear uma precedure no xml e na classe??

Gabriel Bauermann disse...

Olá Reinaldo. Eu pretendo falar mais sobre NHibernate. Ainda não tive tempo de me aprofundar no assunto. Mas enquanto eu não volto a abordar o NHibernate, dá uma conferida neste material: http://ayende.com/Blog/archive/2006/09/18/UsingNHibernateWithStoredProcedures.aspx.
Acho que vai te ajudar.
Abraço

Unknown disse...

sei que isso já antigo, então não sei se o problema quetenho é por esse motivo, mas consegui mapear tudo certinho, porém quando faço "new Configuration()" é lançada uma exceção "O inicializador de NHibernate lançou uma exceção". Em "View Details" fala algo sobre LoggerProvider, mas não sei o que fazer. Pesquisei muito e não encontrei nada. O que pode Ser?

Gabriel Bauermann disse...

Bom dia Cícero. Sem saber mais detalhes, não tenho como te ajudar. Mas de qqr forma, acho q estes fóruns podem ser mais úteis:

- http://social.msdn.microsoft.com/Forums/pt-br/categories/
- https://community.jboss.org/en/hibernate/nhibernate
- https://groups.google.com/forum/?fromgroups#!forum/nhibernate-br

Se encontrar o problema, fique a vontade para compartilhar com a gente.

Abraço

Postar um comentário