O Castle ActiveRecord é uma implementação do pattern Active Record desenvolvido em .NET em cima do NHibernate.
Ele faz parte do pacote de frameworks do projeto Castle Projet, e tem forte influencia da implementação do Active Record do framework Ruby On Rails.
Entre as muitas características dele vale destacar, a possibilidade de mapeamento de classes via atributos e não dos famigerados arquivos xml e um mecanismo de validação eficiente e flexível.
Criando o projeto
Acesse a página de download do projeto, baixe o arquivo Castle-net-2.0-release-2007-9-20.zip e descompacte em algum diretório da sua preferência.
Em seguida crie um novo projeto web e faça referência as assemblies abaixo:
Castle.ActiveRecord.dll
Castle.Core.dll
Castle.Components.Validator.dll
Castle.DynamicProxy.dll
NHibernate.dll
Iesi.Collections.dll
log4net.dll
Criando a tabela de Contatos
Crie uma base de dados chamada ContatosAR e em seguida crie uma tabela com a estrutura abaixo.
CREATE TABLE [dbo].[Contatos]( [Id] [int] IDENTITY(1,1) NOT NULL, [Nome] [varchar](255) NOT NULL, [Email] [varchar](255) NOT NULL, CONSTRAINT [PK_Contatos] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
Criando a classe Contato
Agora vamos criar a classe que vai representar a nossa tabela.
using System;
public class Contato
{
private int id;
private string nome;
private string email;
public int Id
{
get { return id; }
set { id = value; }
}
public string Nome
{
get { return nome; }
set { nome = value; }
}
public string Email
{
get { return email; }
set { email = value; }
}
}
Mapeando a classe Contato
Mapeando a nossa classe para o NHibernate. Só que em vez do xml entra em cena os atributos disponíveis no ActiveRecord.
[ActiveRecord("Contatos")]
public class Contato : ActiveRecordValidationBase<Contato>
{
private int id;
private string nome;
private string email;
[PrimaryKey(PrimaryKeyType.Native, "Id")]
public int Id
{
get { return id; }
set { id = value; }
}
[Property("Nome")]
[ValidateNonEmpty("Nome é requirido")]
[ValidateLength(1, 255, "Nome deve ter no máximo 255 caracteres")]
public string Nome
{
get { return nome; }
set { nome = value; }
}
[Property("Email")]
[ValidateNonEmpty("E-mail é requirido")]
[ValidateLength(1, 255, "E-mail deve ter no máximo 255 caracteres")]
[ValidateEmail("E-mail inválido")]
public string Email
{
get { return email; }
set { email = value; }
}
}
Configurando o ActiveRecord
No arquivo Web.Config adicione o código abaixo e altere a chave hibernate.connection.connection_string para apontar para a sua instância do SQL Server.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="activerecord"
type="Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord" />
</configSections>
<activerecord isWeb="true">
<config>
<add key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver" />
<add key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2005Dialect" />
<add key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider" />
<add key="hibernate.connection.connection_string"
value="Data Source=.;Initial Catalog=ContatosAR;Integrated Security=True" />
</config>
</activerecord>
</configuration>
E no arquivo Global.asax adicione o código abaixo.
<%@ Application Language="C#" %>
<%@ Import Namespace="Castle.ActiveRecord" %>
<%@ Import Namespace="Castle.ActiveRecord.Framework" %>
<%@ Import Namespace="Castle.ActiveRecord.Framework.Config" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
IConfigurationSource source = ActiveRecordSectionHandler.Instance;
ActiveRecordStarter.Initialize(source, typeof(Contato));
}
</script>
Listando os contatos
Agora, com o ActiveRecord configurado, vamos criar uma página para listar todos os contatos cadastrados na base de dados (nenhum até o momento).
<asp:GridView ID="gvContatos" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:HyperLinkField DataNavigateUrlFields="Id"
DataNavigateUrlFormatString="EditarContato.aspx?Id={0}"
DataTextField="Nome" HeaderText="Nome" />
<asp:BoundField DataField="Email" HeaderText="E-mail" />
</Columns>
</asp:GridView>
ListarContatos.aspx.cs
public partial class ListarContatos : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
gvContatos.DataSource = Contato.FindAll();
gvContatos.DataBind();
}
}
Inserindo um contato
Montando o formulário de inserção. De propósito vou deixar para fazer a validação no servidor.
<h3>Novo contato</h3>
<asp:Panel ID="pnMensagem" runat="server" Visible="false">
<asp:Label ID="lblMensagem" runat="server" />
</asp:Panel>
<p>
<asp:Label ID="lblNome" runat="server" AssociatedControlID="txtNome">Nome:</asp:Label>
<asp:TextBox ID="txtNome" runat="server" Columns="40" MaxLength="255"></asp:TextBox>
</p>
<p>
<asp:Label ID="lblEmail" runat="server" AssociatedControlID="txtEmail">E-mail:</asp:Label>
<asp:TextBox ID="txtEmail" runat="server" Columns="40" MaxLength="255"></asp:TextBox>
</p>
<asp:Button ID="btnSalvar" runat="server" OnClick="btnSalvar_Click" Text="Salvar" />
ou <a href="ListarContatos.aspx">Voltar</a>
NovoContato.aspx.cs
public partial class NovoContato : System.Web.UI.Page
{
protected void btnSalvar_Click(object sender, EventArgs e)
{
pnMensagem.Visible = true;
lblMensagem.Text = "";
Contato contato = new Contato();
contato.Nome = txtNome.Text;
contato.Email = txtEmail.Text;
if (contato.IsValid())
{
contato.Create();
lblMensagem.Text = "Contato criado com sucesso.";
txtNome.Text = "";
txtEmail.Text = "";
}
else
{
foreach (string s in contato.ValidationErrorMessages)
lblMensagem.Text += s;
}
}
}
Editando um contato
<h3>Editar contato</h3>
<asp:Panel ID="pnMensagem" runat="server" Visible="false">
<asp:Label ID="lblMensagem" runat="server" />
</asp:Panel>
<p>
<asp:Label ID="lblNome" runat="server" AssociatedControlID="txtNome">Nome:</asp:Label>
<asp:TextBox ID="txtNome" runat="server" Columns="40" MaxLength="255"></asp:TextBox>
</p>
<p>
<asp:Label ID="lblEmail" runat="server" AssociatedControlID="txtEmail">E-mail:</asp:Label>
<asp:TextBox ID="txtEmail" runat="server" Columns="40" MaxLength="255"></asp:TextBox>
</p>
<asp:Button ID="btnSalvar" runat="server" OnClick="btnSalvar_Click" Text="Salvar" />
ou <a href="ListarContatos.aspx">Voltar</a>
EditarContato.aspx.cs
public partial class EditarContato : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Contato contato = Contato.Find(Convert.ToInt32(Request.QueryString["Id"]));
txtNome.Text = contato.Nome;
txtEmail.Text = contato.Email;
}
}
protected void btnSalvar_Click(object sender, EventArgs e)
{
pnMensagem.Visible = true;
lblMensagem.Text = "";
Contato contato = Contato.Find(Convert.ToInt32(Request.QueryString["Id"]));
contato.Nome = txtNome.Text;
contato.Email = txtEmail.Text;
if (contato.IsValid())
{
contato.Update();
lblMensagem.Text = "Dados do contato atualizados com sucesso.";
}
else
{
foreach (string s in contato.ValidationErrorMessages)
lblMensagem.Text += s;
}
}
}
Código do projeto
O código do projeto está disponivel para download.
Ele foi desenvolvido usando o Microsoft Visual Web Developer 2008 Express Edition com o SQL Server Express 2005.
Em breve
Depois dessa passada superficial vou tentar preparar uma série de posts detalhando mais as funcionalidades do framework.
by Roberta
15 Oct 2008 at 10:47
Há tempos procuro um site que me ajude na implementação do active record no meu projeto.
Enfim encontrei um que retirou todas as minhas dúvidas, além de um exemplo prático!
Parabéns! Foi um ótimo artigo
by Fabiano França
15 Oct 2008 at 11:12
Roberta,
Fico feliz em ter ajudado. Qualquer nova dúvida você pode entrar em contato.
by Fabiano Lira
14 Nov 2008 at 09:11
muito bom o artigo, estava difícil achar um artigo tão prático pra quem está aprendendo como usar.
cheguei a pensar até em fazer um artigo sobre isso pois n achei nada tão claro.
deveria ter um link no site do Castle apontando pra cá.
Parabéns Ótimo Artigo!
by Itamar
20 Feb 2009 at 19:21
Não sou de escrever elogiando mas tenho que dar a mão a palmatória, bastante útil esse artigo, parabéns.
by Marcelo
25 May 2009 at 10:30
Bah, matou a pau, muito bom o conteúdo desse artigo, parabéns mesmo, me ajudou tirando muitas dúvidas e um bom exemplo prático, ótima iniciativa, um dia vou retribuir publicando uma coisa útil como essa.
by Maia
13 Oct 2009 at 09:12
Boa tarde!
Para as versões ActiveRecord 2.0 e NHibernate 2.1, existe alguma mudança no Web.Config? Atualizei as versões das Dll´s sendo que por dentro do VS2008 tudo roda 100%, agora quando publico no IIS6 ou IIS7 apresenta o seguinte erro:
Erro de Servidor no Aplicativo ‘/CRM’.
An ActiveRecord class (CRMModel.Model.CrmUsuario) was used but the framework seems not properly initialized. Did you forget about ActiveRecordStarter.Initialize() ?
Nas versões anteriores não tenho problemas, ou seja, roda tudo certinho.
Web.config:
Se alguém tiver alguma dica, agradeço.
Maia.
by Maia
13 Oct 2009 at 09:13
Web.Config