C# - Usando o NHibernate 2.1 com SharpDevelop 3.1 e MySQL/SQL Server II


Se você esta chegando agora é bom se situar...

Na primeira parte deste artigo eu defini o nosso objetivo, defini os recursos que iríamos usar, criei o banco de dados e as tabelas no MySQL e no SQL Server, criei o projeto no SharpDevelop, defini as referências usadas no projeto, a classe do nosso domínio e o arquivo de configuração para o NHibernate.

Nesta última parte do artigo vamos definir o arquivo de configuração da aplicação e realizar as operações usando os recursos do NHibernate.

Definindo o arquivo de configuração da aplicação

Se você já criou aplicações na plataforma .NET com acesso a dados usando DataSets ou DataReaders deve estar familiarizado com o conceito de armazenar a string de conexão em um arquivo de configuração App.Config ou Web.Config.

Pois para o NHibernate o conceito é o mesmo. Você tem que definir em um arquivo de configuração algumas informações que orientam o NHibernate quanto o banco de dados que esta sendo usado a string de conexão e outros detalhes.

Como estamos trabalhando com uma aplicação Windows Forms vamos criar um arquivo app.config.

Com o projeto aberto no SharpDevelop, no menu Projeto selecione -> Adicionar Novo Item;

Na janela Novo Arquivo selecione a Categoria Misc e em Modelos selecione App.Config File e clique Criar;

A seguir defina no arquivo XML criado o seguinte conteúdo:

<?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="connection.driver_class">
    <!--NHibernate.Driver.SqlClientDriver-->
    NHibernate.Driver.MySqlDataDriver
</property>
<property name="connection.connection_string">
   <!--Server=.\SQLEXPRESS;database=AloMundo;Integrated Security=SSPI;-->
   Server=localhost;Database=alomundo;User ID=root;Password=gpxpst
</property>
<property name="dialect">
   <!--NHibernate.Dialect.MsSql2000Dialect	-->
   NHibernate.Dialect.MySQLDialect
</property>
<property name="show_sql">
   false
</property>
<property name="hbm2ddl.keywords">
   none
</property>
<property name="proxyfactory.factory_class">
   NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
</property>
</session-factory>
</hibernate-configuration>
</configuration>

Lembrando que esta configuração vale para a versão 2.0 do NHiberante ou superior.

O arquivo pode parecer complicado mas na verdade ele apenas defini alguns parâmetros para a aplicação os quais são:

- <property name="connection.provider"> - define o provedor usado pelo NHibernate

NHibernate.Connection.DriverConnectionProvider

- <property name="connection.driver_class"> - define o driver usado para conexão com o banco de dados. Observe que temos dois valores: um que esta comentado e outro que esta ativo. Fizemos assim pois vamos usar dois banco de dados: O MySQL e o SQL Server logo para o banco de dados ativo usamos o driver correspondente.

<!--NHibernate.Driver.SqlClientDriver-->
NHibernate.Driver.MySqlDataDriver

- <property name="connection.connection_string"> - define a string de conexão com o banco de dados. Novamente temos dois valores um para o SQL Server e outro para o MySQL.

<!--Server=.\SQLEXPRESS;database=AloMundo;Integrated Security=SSPI;-->
Server=localhost;Database=alomundo;User ID=root;Password=xxxxxx

- <property name="show_sql"> - Define se os comandos SQL serão exibidos ou não.
false

<property name="proxyfactory.factory_class"> - Define o proxy usado pelo NHibernate
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle

O NHibernate usa este arquivo para saber como tratar com o banco de dados e como usá-lo.

Como eu já mencionei uma das grandes vantagens do NHibernate é poder abstrair os comandos SQL e a independência do banco de dados. Quando usamos ADO .NET temos todo um trabalho relacionado com a definição de objetos para conexão e persistência de dados bem como dos comandos SQL envolvidos.

Apenas para ilustrar, a figura abaixo mostra uma comparação de um exemplo de arquitetura usando a ADO .NET e o NHibernate.

Pois bem, se com o NHibernate eu não tenho que escrever comandos SQL como tenho que fazer para realizar operações de persistência ?

O NHibernate utiliza as interface ISession, ITransaction e IQuery para realizar a interação e a persistência com o banco de dados, portanto para usar esses recursos do NHibernate temos que usar essas interfaces. Onde:

Vamos então definir uma aplicação Windows Forms bem simples onde iremos realizar operações de consulta e persistência de dados usando esses recursos.

Vamos definir uma pequena aplicação que realiza o controle de funcionários de uma empresa. Nela iremos realizar as seguintes operações: Consultar e exibir empregados, criar , atualizar e excluir empregados. Para isso defini no formulário padrão da aplicação a o seguinte leiaute para a interface:

Controles usados :
  • ListBox
  • Button
  • TextBox
  • GroupBox

Todas as operações que iremos realizar devem usar a interface ISession e abrir uma sessão a partir da qual o NHibernate obtém as informações que definimos nos arquivos de configuração. Nosso primeiro passo será definir um método que usa a interface ISession. Eu vou fazer isso no próprio formulário da aplicação e não em uma camada separada como seria o correto pois quero focar em mostrar como usar esses recursos básicos do NHibernate e não estou preocupado com as boas práticas neste momento.

Definindo o código da aplicação

Então no próprio formulário vamos primeiro definir os namespaces que vamos usar na aplicação:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using NHibernate;
using NHibernate.Cfg;
using System.Reflection;
using MySql.Data.MySqlClient;
using MySql.Data;

A seguir vamos definir o método estático OpenSession que irá definir uma sessão para o NHibernate conforme o código abaixo:

//define uma sessão
static ISession OpenSession()
{
	   if(factory == null)
	   {
		   try{
		      Configuration c = new Configuration();
		      c.AddAssembly(Assembly.GetCallingAssembly());
		      factory = c.BuildSessionFactory();
		    }
	   	    catch (Exception ex)
	   	    {
	   	    	 MessageBox.Show(" Erro : " + ex.Message.ToString());
	   	    	 Application.Exit();
	   	     }
              }
	   return factory.OpenSession();				      
}

O código deste método carrega as informações dos arquivos hbml.xml definidos no projeto:
Configuration c = new Configuration();
c.AddAssembly(Assembly.GetCallingAssembly());


e do arquivo App.Config da aplicação:
factory = c.BuildSessionFactory();

criando uma sessão que será retornada e usada em nossa aplicação:
return factory.OpenSession();

Todas as operações que iremos realizar vão usar esta sessão que foi criada.

Para começar vou mostrar como acessar os dados dos empregados e exibi-los no formulário no controle ListBox.

Isso é feito quando o usuário clica no botão Exibir Empregados. O código associado ao evento Click deste botão é o seguinte:

//exibe os empregados
void BtnExibirClick(object sender, EventArgs e)
{
	using (ISession session = OpenSession())
	{
		try{
			IQuery query = session.CreateQuery("from Empregado as emp order by emp.nome asc");
			IList<Empregado> procuraEmpregados = query.List<Empregado>();
			lstEmpregados.Items.Clear();
			lstEmpregados.Items.Add("Empregado(s) encontrado(s) : " + procuraEmpregados.Count);
		
			foreach( Empregado empregado in procuraEmpregados )
				lstEmpregados.Items.Add(empregado.empregadoID());
		        }
	catch (Exception ex)
	{
	      MessageBox.Show(" Erro : " + ex.Message.ToString());
	 }
     }			
}		

Neste código estamos usando a linguagem de consulta do NHibernate chamada HQL- Hibernate Query Language. Ela é parecida com a SQL mas é orientada a objetos e possui recursos de herança, polimorfismo e associação.

Nota: para mais detalhes sobre a HQL consulte o site oficial do NHibernate: https://www.hibernate.org/hib_docs/nhibernate/html/queryhql.html

Primeiro obtemos a sessão que foi criada e definimos a consulta para obter os empregados da entidade Empregado que foi mapeada do banco de dados.

IQuery query = session.CreateQuery("from Empregado as emp order by emp.nome asc");

Em seguida obtemos uma coleção dos objetos Empregado:

IList<Empregado> procuraEmpregados = query.List<Empregado>();

Exibimos o total de empregados encontrados:

lstEmpregados.Items.Add("Empregado(s) encontrado(s) : " + procuraEmpregados.Count);

Percorremos a coleção e exibimos o ID e o nome do empregado no ListBox:

foreach( Empregado empregado in procuraEmpregados )
        lstEmpregados.Items.Add(empregado.empregadoID());

O resultado da execução exibe a seguinte janela:

Vejamos agora como incluir um novo empregado. Para fazer isso o cliente digite o nome do empregado na caixa de texto Nome e aciona o botão Cria Empregado cujo código é dado a seguir:

//chama a rotina para criar um novo empregado
void BtnCriaEmpregadoClick(object sender, EventArgs e)
{
   if (txtNomeEmpregado.Text.Equals(""))
   {
        MessageBox.Show("Informe o nome do Empregado.");
    }
    else
    {
       string nomeEmpregado = txtNomeEmpregado.Text;
       CriaEmpregadoSalvandoNoBancodeDados(nomeEmpregado);
    }
}

Neste código estamos apenas chamando a rotina CriaEmpregadoSalvandoNoBancoDeDados() passando o nome do empregado. A seguir temos o código desta rotina :

//cria um  novo empregado
static void CriaEmpregadoSalvandoNoBancodeDados(string novoEmpregado)
{
	   Empregado empregado = new Empregado();
               empregado.nome = novoEmpregado ;
	    empregado.gerente = null ;
	
	   using (ISession session = OpenSession())
	   {
	   	  using( ITransaction transaction = session.BeginTransaction())
    	      {
	   		  try
	   		  {
   	             session.Save(empregado);
    			     transaction.Commit();
           	 MessageBox.Show("Salvando o novo empregado  :: " + empregado.nome + " ::  no banco de dados");
	   		  }
	   		  catch (Exception ex)
	   		  {
	   		  	 MessageBox.Show(" Erro : " + ex.Message.ToString());
	   		  }
   	  }
	  }
 }

Criamos um novo objeto empregado do tipo Empregado e atribuímos o seu nome e o gerente como null.

Usamos a sessão que foi criada e iniciamos uma transação para em seguida usar o método Save e salvar os dados na base de dados.

Por trás dos panos o NHibernate esta executando o comando SQL:

Insert into Empregado(nome,gerente) values ('James Taylor',null)

Observe que a coluna id não esta sendo inicializada pois esta propriedade é gerada automaticamente pelo banco de dados.

O resultado da execução desta operação e exibida na figura abaixo:

Para atualizar as informações de um empregado precisamos informar o nome que desejamos alterar e o novo nome. e clicar no botão Atualizar Empregado que possui o seguinte código:

//chama a rotina para atualizar o nome do empregado
void btnAtualizaCriaNovoEmpregadoClick(object sender, EventArgs e)
{
	if(txtNomeAnteriorEmpregado.Text.Equals("") || txtNovoNomeEmpregado.Text.Equals(""))
	{
	   	MessageBox.Show("Informe o nome do Empregado e o novo Nome.");
	}
	else
	{
	   string nomeAnteriorEmpregado = txtNomeAnteriorEmpregado.Text;
	   string noveNomeEmpregado     = txtNovoNomeEmpregado.Text;
		   AtualizaEmpregado(nomeAnteriorEmpregado,noveNomeEmpregado);
	}
}

Aqui usamos a rotina AtualizaEmpregado() passando o nome anterior e o novo nome. O código desta rotina é dado abaixo:

//atualiza o nome de um empregado
static void AtualizaEmpregado(string nomeEmpregado, string novoNomeEmpregado)
{
	using (ISession session = OpenSession())
	{
	  using (ITransaction transaction = session.BeginTransaction())
	  {
		try{
			IQuery q = session.CreateQuery("from Empregado where nome = '" + nomeEmpregado + "'");
			Empregado empregado = q.List<Empregado>()[0];
			empregado.nome = novoNomeEmpregado;
			transaction.Commit();
			MessageBox.Show("Empregado  :: " + nomeEmpregado + "  :: foi Atualizado ");
	    }
   	    catch (Exception ex)
   	    {
   	   	    MessageBox.Show(" Erro : " + ex.Message.ToString());
   	    }
       }
     }
}

Usamos a sessão que foi criada e iniciamos uma transação.

Criamos uma consulta HQL para o obter o objeto empregado com o nome informado e atualizamos o nome anterior pelo informado e em seguida salvamos as alterações consolidando (Commit) a transação. Abaixo vemos o resultado da operação:

Para excluir um empregado o cliente informa o nome e clica no botão Excluir. Esta operação usa a rotina ExcluiEmpregado exibida abaixo:

//exclui um  novo empregado
static void ExcluiEmpregado(string nomeEmpregado)
{
	using (ISession session = OpenSession())
	{
	  using (ITransaction transaction = session.BeginTransaction())
	  {
		try{
			IQuery q = session.CreateQuery("from Empregado where nome = '" + nomeEmpregado + "'");
			Empregado empregado = q.List<Empregado>()[0];
			session.Delete(empregado);
			transaction.Commit();
			MessageBox.Show("Empregado  :: " + nomeEmpregado + "  :: foi excluido. ");
	    }
   	    catch (Exception ex)
   	    {
   	   	    MessageBox.Show(" Erro : " + ex.Message.ToString());
   	    }
       }
   }			
}		

Usamos a sessão que foi criada e iniciamos uma transação.

Definimos uma consulta HQL para obter o objeto empregado pelo nome informado e usamos o método Delete() para excluir o objeto consolidando(comitando) a transação. Abaixo vemos o resultado da exclusão:

Podemos repetir todo o processo acima usando o banco de dados SQL Server que foi criado na primeira parte do artigo. Para isso basta alterar o arquivo de configuração App.Config usando os valores que estão comentados para o driver, a string de conexão e o dialeto e comentando os valores usados para o MySQL. Feito isso basta rodar a aplicação novamente que o acesso será feito no SQL Server. No resto é tudo igualzinho ao que já foi mostrado.

Com isso mostrarmos como realizar as operações básicas de consulta e persistência (CRUD) usando o NHibernate e a linguagem C# e usando dois banco de dados para mostrar a versatilidade do NHibernate.

Pegue o projeto completo aqui: NHibernate_AloMundo.zip

Aguarde em breve outros artigos sobre o NHibernate.

Eu sei é apenas NHibernate, mas eu gosto...

Referências:


José Carlos Macoratti