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 ClassNeste 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 ClassEste 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 SubOlhe 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 SubNeste 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 /> SubPara 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 SubEste 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 SubO 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 SubNo 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…








