Dev (Back & Front)ARTIGO

NHibernate – usando o ActiveRecord – Parte 02

Na primeira parte deste artigo eu apresentei o
ActiveRecord. Agora vou mostrar como usar este recurso em um projeto
Windows Forms usando a linguagem VB .NET.

Apenas recordando, o ActiveRecord é um
recurso que facilita a utilização do NHibernate poupando o trabalho de criar os
arquivos XML de mapeamento OR/M, para isso é criada uma classe onde usamos
atributos para realizar esta tarefa.

Obs:


O projeto Castle ActiveRecord oferece uma maneira rápida
e fácil para implementar o padrão de registro ativo para aplicativos do
Microsoft com base no .NET Framework.

Usando o ActiveRecord e
o NHibernate em uma aplicação Windows Forms

Para que você possa entender como  implementar
a utilização dos recursos do ActiveRecord em sua aplicação C# ou VB .NET,
eu vou criar um exemplo usando a linguagem VB .NET no qual iremos realizar as
seguintes tarefas:

  • Criação do banco de dados e da
    tabela usando o SQL Server 2008 Express;
  • Criação do projeto WIndows Forms;
  • Definição das referências para
    as DLLs do NHibernate e do ActiveRecord;
  • Criação das classe para realizar
    o mapeamento;
  • Definição do arquivo de
    configuração;
  • Inicializando o Framework;
  • Usando as classes na aplicação
    Windows Forms;

1. Criando o banco de dados e a
tabela

A primeira coisa que eu vou fazer será criar o
banco de dados Clientes e a tabela contatos no SQL Server 2008.
Eu poderia criar as minhas classes de domínio e mandar gerar o banco de dados e
as tabelas, mas por ser uma introdução vou seguir o caminho feliz.

Eu vou criar o banco de dados e a tabela usando o
Microsoft SQL Server Management Studio. Abaixo
vemos a estrutura da tabela definida com os campos : id, nome e email,
sendo que id é um campo chave primária do tipo identity;

2. Criando o projeto Windows
Forms e fazendo a referência ao NHibernate e ao ActiveRecord

Abra agora o Visual Basic
2008 Express Edition e crie um novo projeto do tipo WIndows Forms
Application com o nome NHibernateActiveRecordDemo;

A seguir clique com o botão direito do mouse sobre
o nome do projeto e selecione a opção Add Reference:

Na guia Browse primeiro localize onde você
instalou os arquivos do NHibernate e inclua as referências conforme a
figura 1.0;

Em seguida repita a operação selecionando as dlls
na pasta onde você instalou as dlls do ActiveRecord conforme a figura
2.0;

3. Criando a classe para efetuar
o mapeamento OR/M

No menu Project selecione Add Class e
informe o nome Contato.vb. Esta classe deverá herdar da classe
ActiveRecordBase e usar os atributos do ActiveRecord para realizar o
mapeamento OR/M para a tabela Contatos.

Imports Castle.ActiveRecord<br /><br /><ActiveRecord("contatos")> _<br />Public Class Contato<br />Inherits ActiveRecordBase(Of Contato)<br /><br />    Private m_id As Integer<br />    Private m_nome As String<br />    Private m_email As String<br /><br /><PrimaryKey("Id")> _<br />    Public Property Id() As Integer<br />        Get<br />            Return (m_id)<br />        End Get<br />        Set(ByVal value As Integer)<br />            m_id = value<br />        End Set<br />    End Property<br /><br />    <[Property]("Nome")> _<br />    Public Property Nome() As String<br />        Get<br />            Return (m_nome)<br />        End Get<br />        Set(ByVal value As String)<br />            m_nome = value<br />        End Set<br />    End Property<br /><br />    <[Property]("Email")> _<br />    Public Property Email() As String<br />        Get<br />            Return (m_email)<br />        End Get<br />        Set(ByVal value As String)<br />            m_email = value<br />        End Set<br />    End Property<br /><br />End Class

Neste arquivo
usamos o namespace Castle.ActiveRecord
para ter acesso às classes e aos atributos;

A classe Contato herda da classe
ActiveRecordBase() e dessa forma poderá
usar os métodos para mapear e persistir informações para o banco de dados;

Definimos 3 propriedades e usamos os seguintes
atributos:


<PrimaryKey(“Id”)> _
– <[Property](“Nome”)> _
– <[Property](“Email”)> _

Para mapear as propriedades para os campos da
tabela Contatos.

Não definimos explicitamente o nome da tabela
nem seu esquema, mas o ActiveRecord é capaz de inferir estas informações.

Observe
que a classe Contato estende a classe ActiveRecordBase e usa
atributos para sinalizar quais propriedades mapeiam para colunas na
tabela de banco de dados e a coluna que serve como a chave primária.


A classe de ActiveRecordBase define métodos de instância, como criar
e salvar e métodos estáticos incluindo Find, FindAll e DeleteAll.

Junto com
a criação da classe Contatos, você também vai precisar definir algumas
configurações de configuração, como a seqüência de conexão de banco de dados
e algumas poucas opções específicas de NHibernate.

Mas não há
necessidade de escrever nenhum código de acesso a dados. que é
realizado para você automaticamente pelo projeto de


ActiveRecord e
NHibernate.


Na verdade, você nem precisa ter criado as tabelas do banco de dados neste
ponto, como o projeto ActiveRecord pode automaticamente gerar as tabelas com
base nas classes que você criou. (Não vou usar este recursos neste
exemplo.)

Obs: Nosso
exemplo possui somente uma tabela, mas podemos trabalhar com relacionamentos
entre tabelas.
A sintaxe do atributo do projeto ActiveRecord também é usada para estabelecer
relacionamentos entre classes.
Por exemplo,
os atributos HasMany e BelongsTo podem ser usados em uma classe
pai e filho, respectivamente, para indicar uma relação
um-para-muitos.

4. Criando o arquivo XML para
definir as configurações usadas pelo NHibernate

Vamos agora criar o arquivo de configuração para o
NHibernate com o nome AppConfig.xml conforme abaixo:

<?xml<br />version="1.0"<br />encoding="utf-8"<br />?><br /><br /><activerecord><br /><br /><config><br /><br />    <add<br /><br />            key="connection.driver_class"<br /><br />           value="NHibernate.Driver.SqlClientDriver" /><br /><br />     <add<br /><br />            key="dialect"<br /><br />            value="NHibernate.Dialect.MsSql2005Dialect" /><br /><br />     <add<br /><br />            key="connection.provider"<br /><br />           value="NHibernate.Connection.DriverConnectionProvider" /><br /><br />     <add<br /><br />             key="connection.connection_string"<br /><br />             value="Data Source=.\SQLEXPRESS;Initial Catalog=Clientes;Integrated Security=SSPI" /><br /><br />      <add<br /><br />            key="proxyfactory.factory_class" /><br /><br />            value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle"<br /><br /></config><br /><br /></activerecord> 

Neste arquivo estamos definindo as seguintes
informações:

  • O driver do banco de dados
    usados no projeto:  key=”connection.driver_class”
  • O dialeto do banco de dados : 
    key=”dialect”
  • O provedor da conexão :
     key=”connection.provider”
  • A string de conexão usada:
     key=”connection.connection_string”
  • O proxy :   key=”proxyfactory.factory_class”
    />

Estas informações referem-se ao banco de dados que
estamos usando, no caso o SQL Server 2008 Express.

Este arquivo XML deve estar localizado na pasta
bin/debug quando o projeto estiver sendo executado no modo de debug.

Neste momento o seu projeto deverá ter a seguinte
estrutura:

Vamos partir para a criação da interface e
utilização na prática do ActiveRecord.

5. Criando o arquivo
para inicializar o framework

No menu Project selecione Add Class e
informe o nome App.vb e inclua nele o seguinte código:

Imports Castle.ActiveRecord<br />Imports Castle.ActiveRecord.Framework<br />Imports Castle.ActiveRecord.Framework.Config<br /><br />Public Class App<br /><br />    Public Shared Sub Main()<br />        Dim source As XmlConfigurationSource = New XmlConfigurationSource("AppConfig.xml")<br />ActiveRecordStarter.Initialize(source, GetType(Contato))<br />    End Sub<br /><br />End Class

Este arquivo irá ler as informações do arquivo
AppConfig.xml criado e iniciar o framework usando o método Initialize
da classe ActiveRecordStarter.

Temos que executar este código antes de poder usar
os recursos do ActiveRecord, e, sem fazer isso o projeto não vai
funcionar.

6. Criando a interface com o
usuário

Agora vamos criar uma interface usando o formulário
form1.vb conforme a figura abaixo:

Iremos implementar as funcionalidades de listar,
incluir, alterar e excluir informações do banco de dados usando o NHibernate e o
mapeamento gerado pelo ActiveRecord.

a. Listando os
contatos no DataGridView

Vamos primeiro definir o código para listar
as informações da tabela Contatos no evento Click do botão
Listar:

Private Sub btnListar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnListar.Click<br />        Try<br />   gdvContato.DataSource = Contato.FindAll()<br />        Catch ex As Exception<br />            MsgBox(" ERRO : " & ex.Message)<br />        End Try<br />    End Sub

Olhe bem o código que usamos; ele é responsável
por obter os dados da tabela contatos e exibir no datagridview.

Cadê o comando SQL, a conexão,
os objetos
Command, Connection , dataset, datable, dataadapter ????

Esta é a vantagem em usar o NHibernate. Não
precisamos de nada nisso. 

Estamos usando apenas o método FindAll() que
retorna todas as instâncias do tipo Contato. Lembre-se de que a nossa classe
Contato herda da classe
ActiveRecordBase(Of Contato).

b. Criando um novo
contato

Para criar um novo contato eu vou incluir um novo
formulário a partir do menu Project opção Add Windows Forms com o nome
Novo.vb conforme o leiaute abaixo:

Este
formulário possui 3 Labels, 3 TextBox :

  • txtNome
  • txtEmail

Dois controles Buttons:

  • btnSalvar
  • btnCancelar

Para incluir um novo Contato não é preciso informar
o código do mesmo, visto que este campo foi definido como do tipo identity na
tabela e é gerenciado pelo próprio banco de dados.

O código do evento Click do botão Salvar
do formulário Novo.vb é dado a seguir:

 Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click<br />If txtNome.Text <> String.Empty And txtEmail.Text <> String.Empty Then<br />Dim contato As New Contato<br />contato.Nome = txtNome.Text<br />contato.Email = txtEmail.Text<br />Try<br />contato.Create()<br />txtNome.Text = ""<br />txtEmail.Text = ""<br />MsgBox("Contato criado com sucesso.")<br />Catch ex As Exception<br />MsgBox("Erro " & ex.Message)<br />End Try<br />End If<br />End Sub

Neste código verificamos se foram informados
valores para nome e email nas caixas de texto e em seguida criamos uma instância
da classe Contato.

A seguir atribuímos os valores para o objeto criado
e usamos o método Create() que cria (Salva) uma nova instância do
objeto para o banco de dados.

Limpamos os controles e exibimos uma mensagem ao
usuário. Ocorrendo erro emitimos um aviso.

Antes que eu esqueça o código que abre este
formulário está no evento Click do botão Novo do formulário Form1.vb :

Private <br />    Sub btnNovo_Click(ByVal <br />    sender As <br />    System.Object, ByVal <br />    e As System.EventArgs)<br />    Handles <br />    btnNovo.Click

    
My.Forms.Novo.ShowDialog()

End
Sub

c. Alterando um
contato existente

O código do evento Click do botão Alterar
do formulário Form1.vb  apenas abre um novo formulário que eu crie e chamei
de Alterar.vb. O código é:

Private <br />    Sub btnAlterar_Click(ByVal <br />    sender As <br />    System.Object, ByVal <br />    e As System.EventArgs)<br />    Handles <br />    btnAlterar.Click    <br />    My.Forms.Alterar.ShowDialog()<br />End<br />    Sub

Para alterar um contato eu vou incluir um novo
formulário a partir do menu Project opção Add Windows Forms com o nome
Alterar.vb conforme o leiaute abaixo:

Este
formulário possui 3 Labels, 3 TextBox :

  • txtCodigo
  • txtNome
  • txtEmail

Dois controles Buttons:

  • btnSalvar
  • btnCancelar

Dica: Como os formulário
Novo.vb e Alterar.vb são iguais poderíamos ter usado a herança visual para
criá-los.

Neste formulário a propriedade Enabled do controle txtCodigo foi definida como False, pois não
podemos alterar o código do contato.

No evento Load do formulário Alterar.vb
devemos incluir o código a seguir:

Private Sub Alterar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load<br /><br /> txtCodigo.Text = Form1.gdvContato.CurrentRow.Cells(0).Value.ToString()<br />        txtNome.Text = Form1.gdvContato.CurrentRow.Cells(1).Value.ToString()<br />        txtEmail.Text = Form1.gdvContato.CurrentRow.Cells(2).Value.ToString()<br />    End Sub

Este código apenas obtém os valores selecionados no
controle DataGridView e os exibe nas caixas de texto do formulário
Alterar.vb para que possamos realizar as mudanças.

No evento Click do botão Salvar temos
o seguinte código :

Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click<br /><br />        Dim codigo As Integer = Convert.ToInt32(txtCodigo.Text)<br />        Dim contato As Contato = contato.Find(Convert.ToInt32(codigo))<br /><br />        contato.Nome = txtNome.Text<br />        contato.Email = txtEmail.Text<br />        Try<br />  contato.Update()<br />            MsgBox("Contato atualizado com sucesso.")<br />        Catch ex As Exception<br />            MsgBox("Erro " & ex.Message)<br />        End Try<br />    End Sub

O código obtém o código da caixa de texto e usando
o método Find() procura pelo objeto na coleção de objetos.

Em seguida atribui os valores definidos nas caixas
de texto ao objeto encontrado e usando o método Update() atualiza as
informações no banco de dados.

d. Excluindo um
contato existente

Para excluir um contato existente incluímos o
código abaixo no evento Click do botão Excluir:

 Private Sub btnExcluir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExcluir.Click<br /><br /><br /><br />If (MsgBox("Deseja excluir o contato : " &<br />gdvContato.CurrentRow.Cells(1).Value.ToString(), MsgBoxStyle.YesNo) =<br />MsgBoxResult.Yes) Then<br />            Dim codigo As Integer = Convert.ToInt32(gdvContato.CurrentRow.Cells(0).Value.ToString())<br />            Dim contato As Contato = contato.Find(Convert.ToInt32(codigo))<br /><br /><br /><br />            Try<br />  contato.Delete()<br />                MsgBox("Contato excluído com sucesso.")<br />            Catch ex As Exception<br />                MsgBox("Erro " & ex.Message)<br />            End Try<br />        End If<br />    End Sub

No código, primeiro obtemos o valor do código do
contato a partir da célula do DataGridView selecionada e em seguida, usando o
método Find(), procuramos pelo objeto na coleção de objetos.

Para excluir o objeto usamos o método Delete()
que deleta uma instância do banco de dados.

Abaixo vemos a aplicação em execução mostrando a
alteração de um contato:

Como podemos notar, o NHibernate realiza as
operações de persistência usando os métodos apropriados de forma que no nosso
código não precisamos usar instruções SQL nem os objetos ADO .NET para realizar
a conexão, criar comandos para efetivar tais operações.

De uma forma resumida podemos dizer que por trás
dos panos, quando usamos o ActiveRecord, ocorrem as seguintes tarefas:

  • os comandos SQL são gerados;
  • os comandos SQL são passados
    para o Gerenciador de banco de dados em uso (RDBMS);
  • o RDBMS compila e executa
    o SQL;
  • retorna um enumerable;
  • cria um modelo ActiveRecord para
    cada linha;

Pegue o projeto completo aqui:

NHibernateActiveRecordDemoSQLServer.zip
(sem as referências)

O código ficou mais limpo e fácil de manter e ainda
temos uma vantagem adicional: se precisarmos mudar o banco de dados, a única
alteração que devemos fazer será no arquivo de configuração AppConfig.xml. É isso que irei mostrar na continuação deste
artigo.

Eu sei, é apenas NHibernate, mas eu gosto…

é referência em Visual Basic no Brasil e autor dos livros "Aprenda Rápido: ASP" e "ASP, ADO e Banco de Dados na Internet". Mantenedor do site macoratti.net.

Ver perfil