NHibernate - Usando o ActiveRecord II


Na primeira parte deste artigo eu apresentei o ActiveRecord e 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:

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;

Fig 1.0 - Dlls do NHibernate Fig 2.0 - Dlls do ActiveRecord

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
<ActiveRecord("contatos")> _
Public Class Contato
    Inherits ActiveRecordBase(Of Contato)
    Private m_id As Integer
    Private m_nome As String
    Private m_email As String
    <PrimaryKey("Id")> _
    Public Property Id() As Integer
        Get
            Return (m_id)
        End Get
        Set(ByVal value As Integer)
            m_id = value
        End Set
    End Property

    <[Property]("Nome")> _
    Public Property Nome() As String
        Get
            Return (m_nome)
        End Get
        Set(ByVal value As String)
            m_nome = value
        End Set
    End Property

    <[Property]("Email")> _
    Public Property Email() As String
        Get
            Return (m_email)
        End Get
        Set(ByVal value As String)
            m_email = value
        End Set
    End Property
End Class
Neste arquivo usamos o namespace Castle.ActiveRecord para ter acesso as 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 version="1.0" encoding="utf-8" ?>

<activerecord>

<config>

    <add

            key="connection.driver_class"

           value="NHibernate.Driver.SqlClientDriver" />

     <add

            key="dialect"

            value="NHibernate.Dialect.MsSql2005Dialect" />

     <add

            key="connection.provider"

           value="NHibernate.Connection.DriverConnectionProvider" />

     <add

             key="connection.connection_string"

             value="Data Source=.\SQLEXPRESS;Initial Catalog=Clientes;Integrated Security=SSPI" />

      <add

            key="proxyfactory.factory_class" />

            value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle"

</config>

</activerecord>

Neste arquivo estamos definindo as seguintes informações:

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
Imports Castle.ActiveRecord.Framework
Imports Castle.ActiveRecord.Framework.Config

Public Class App
    Public Shared Sub Main()
        Dim source As XmlConfigurationSource = New XmlConfigurationSource("AppConfig.xml")
        ActiveRecordStarter.Initialize(source, GetType(Contato))
    End Sub
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
        Try
            gdvContato.DataSource = Contato.FindAll()
        Catch ex As Exception
            MsgBox(" ERRO : " & ex.Message)
        End Try
    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 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
        If txtNome.Text <> String.Empty And txtEmail.Text <> String.Empty Then
            Dim contato As New Contato
            contato.Nome = txtNome.Text
            contato.Email = txtEmail.Text
            Try
                contato.Create()
                txtNome.Text = ""
                txtEmail.Text = ""
                MsgBox("Contato criado com sucesso.")
            Catch ex As Exception
                MsgBox("Erro " & ex.Message)
            End Try
        End If
    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 esta no evento Click do botão Novo do formulário Form1.vb :

Private Sub btnNovo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 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 Sub btnAlterar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAlterar.Click

    My.Forms.Alterar.ShowDialog()

End 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
        txtCodigo.Text = Form1.gdvContato.CurrentRow.Cells(0).Value.ToString()
        txtNome.Text = Form1.gdvContato.CurrentRow.Cells(1).Value.ToString()
        txtEmail.Text = Form1.gdvContato.CurrentRow.Cells(2).Value.ToString()
    End Sub

 

Este código apensa 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
        
        Dim codigo As Integer = Convert.ToInt32(txtCodigo.Text)
        Dim contato As Contato = contato.Find(Convert.ToInt32(codigo))
        contato.Nome = txtNome.Text
        contato.Email = txtEmail.Text
        Try
            contato.Update()
            MsgBox("Contato atualizado com sucesso.")
        Catch ex As Exception
            MsgBox("Erro " & ex.Message)
        End Try
    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
        If (MsgBox("Deseja excluir o contato : " & gdvContato.CurrentRow.Cells(1).Value.ToString(), MsgBoxStyle.YesNo) = MsgBoxResult.Yes) Then
            Dim codigo As Integer = Convert.ToInt32(gdvContato.CurrentRow.Cells(0).Value.ToString())
            Dim contato As Contato = contato.Find(Convert.ToInt32(codigo))
            Try
                contato.Delete()
                MsgBox("Contato excluído com sucesso.")
            Catch ex As Exception
                MsgBox("Erro " & ex.Message)
            End Try
        End If
    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:

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.: NHibernate - Usando o ActiveRecord com MySQL III

Eu sei é apenas NHibernate mais eu gosto...

Referências:


José Carlos Macoratti