Você verá neste artigo o que é SubSonic, como utilizá-lo para desenvolver rapidamente aplicações Web, e como ele pode nos proporcionar uma alta produtividade em nosso desenvolvimento do dia a dia.

O SubSonic é uma ferramenta para auxiliar nas tarefas mecânicas que envolvem a construção de aplicações Web, e portanto seu principal objetivo é proporcionar um aumento de produtividade do desenvolvedor.


Guia do artigo:

O SubSonic pode ser utilizado em situações onde necessitamos aplicar boas práticas de desenvolvimento, e manter uma arquitetura separada em camadas. Para esse tipo de aplicação, o SubSonic é uma ótima opção se você precisa de produtividade no desenvolvimetno das suas aplicações.

Quando desenvolvemos aplicações Web utilizando a plataforma .Net, uma organização na arquitetura é sempre bom para que possíveis manutenções no futuro ou até mesmo o entendimento do código-fonte do programa, sejam compreendidas de forma fácil e rápida. O SubSonic é uma ferramenta que nos auxilia na geração de uma camada de acesso a dados nas aplicações, utilizando a plataforma .. E como o SubSonic gera boa parte do código dessas camadas, nós temos um significativo aumento de produtividade no desenvolvimento de aplicações Web.

Hoje em dia muitas aplicações em diversos ramos, utilizam um banco de dados relacional para armazenar suas informações. Este banco de dados deve ser estruturado para manter uma representação de todo o tráfego da informação processada pelo software, para que isso seja de fácil entendimento em futuras manutenções.

Uma das boas práticas em aplicações que fazem uso de uma arquitetura em camadas, é possuir uma específica para cuidar do acesso aos dados. Isso além de ser um ponto positivo para o sucesso do software/projeto, contribui para a simplicidade tanto no código-fonte do software como no acesso centrado às informações contidas em um banco de dados. Vamos ver neste artigo como o SubSonic pode nos fornecer uma contribuição para nossa camada de acesso a dados sem muito esforço, e como tirar bons proveitos desta ferramenta de geração de código.

O projeto SubSonic

SubSonic é uma ferramenta gratuita e de código aberto que realiza a geração de código para facilitar o acesso a banco de dados relacional. Esse projeto foi iniciado por Rob Conery, e com o tempo teve a contribuição de outros desenvolvedores.

Para os exemplos criados neste artigo, foi utilizada a versão estável 2.1 do SubSonic, que pode ser baixada através do endereço que você irá encontrar na seção de links, no final deste artigo. Basta fazer o donwload do item chamado Setup-SubSonic-2.1-Final.exe. Esse setup contém toda a documentação, source e binaries do projeto.

No website do SubSonic também existe um fórum, muito interessante, para discussão sobre a ferramenta. Esta versão mantém suporte a bancos de dados como SQL Server 2000 e 2005 (incluindo a versão express), MySQL e Oracle. Temos também suporte ao SQLite, SQL CE e um suporte para PostgreSQL está em desenvolvimento. Pelo fato de ser código aberto, você pode fazer o download do projeto e fazer sua contribuição, seja ela com melhorias internas na ferramenta ou até mesmo desenvolver o suporte a outro banco de dados. No website do Subsonic encontra-se a versão 3 do projeto que foi recentemente lançada, e certamente será tema de novos artigos aqui na WebMobile. Nela já podemos ver que o SubSonic já oferece suporte a linguagem LINQ.

Nota do DevMan

O LINQ (Language Integrated Query) é uma linguagem que surgiu no .NET 3.5, e que oferece suporte à consulta de dados, que podem estar armazenados nas mais diversas formas possíveis.

Os dados a serem consultados podem estar em XML (LINQ para XML), Banco de dados diversos (LINQ-enabled ADO.NET, que incluí LINQ to SQL, LINQ to DataSet e LINQ to Entities) e Objetos (LINQ to Objects). Ou seja, podemos realizar consultas à estas e outras fontes de dados, através de uma linguagem fortemente tipada, como é o LINQ.

O LINQ é parte integrante das linguagens do .NET Framework, e integra novos conceitos, como é o caso das Lambda Expressions e dos Extensions Methods. Através destas novas características, como por exemplo, é possível realizar um “SELECT” através de código C#.

Desde o surgimento do LINQ temos visto uma crescente utilização da linguagem, dada principalmente a sua versatilidade e facilidade para a construção de queries.

Basicamente o SubSonic quando aplicado a um banco de dados, irá percorrer toda a estrutura de tabelas e campos e irá gerar classes para cada tabela do banco de dados. Uma dessas classes é utilizada para representar cada tupla (registro) de uma tabela. Caso você tenha uma tabela chamada Clientes, ele irá gerar uma classe chamada Cliente que irá conter o mapeamento de cada propriedade e campo tabela definida no banco de dados.

De forma geral, a ferramenta irá fazer um mapeamento objeto relacional de cada tabela. A ferramenta gera também uma coleção que irá representar as linhas de uma tabela, se você tem uma tabela chamada Pedidos, ele irá gerar uma classe chamada PedidoColletion que irá operar sobre uma classe também gerada, chamada Pedido. Outra classe também gerada, é destinada a operações CRUD (Create, Read, Update, Delete) que como por exemplo em uma tabela chamada Produtos, iria gerar uma classe chamada ProdutoController. Todas estas classes são geradas com "partial class", o que nos possibilita fazer customizações.

Nota:

Uma classe definida como "partial class", nos permite dividir o código desta em vários arquivos, e quando executamos a aplicação no Visual Studio .Net, o .Net Framework se encarregar e unir os arquivos fontes definidos para esta partial class em questão e compilar como se fosse um único arquivo. Sendo assim, como no caso do SubSonic, podemos definir customizações a parte em outro arquivo e quando necessitarmos fazer uma nova geração de código, não teremos a necessidade de modificar novamente.

Com estas classes você será capaz de fazer métodos CRUD, como seleções, inserções, atualizações e exclusões com um ótimo controle transacional para garantir a consistência. Além disso, as classes que compõe o Subsonic, nos dão a possibilidade de escrever métodos para listagem como se estivéssemos escrevendo linguagem SQL, o que em termos de produtividade quer dizer ganho significativo.

Instalando e configurando no Visual Studio 2008

Feito o download do setup da ferramenta, execute-o e escolha o caminho onde será feita a instalação. Caso você tenha escolhido outro caminho diferente do padrão, deixo claro que precisaremos de alguns arquivos que o setup gera para configurar no Visual Studio, então é importante que você lembre-se deste caminho.

No meu caso estou instalando em C:\Program Files (x86)\SubSonic (Windows 7 RC 1 64 bits). Ao finalizar a instalação, a ferramenta está pronta para ser configurada e utilizada. Irei demonstrar como utilizar a ferramenta sobre o Visual Studio 2008, mas os exemplos também se aplicam sobre o Visual Studio 2005 e Visual Studio 2010 (Beta 1 ou Beta 2).

Antes de iniciarmos a criação de um novo projeto, vamos ver os passos para configurar o SubSonic em nossa IDE de desenvolvimento. Abra o Visual Studio e no menu Tools, selecione a opção External Tools. Esta janela permite que você adicione ferramentas externas que podem ser executadas a partir do Visual Studio, passando parâmetros pré-configurados. Clique no botão Add e confira para que serve cada campo do formulário que e solicitado na Tabela 1.

Tabela 1. Itens para configuração de External Tools no Visual Studio
Title Título descritivo para a exibição no menu do Visual Studio.
Command Caminho para o arquivo que será executado.
Arguments Parâmetros a serem adicionados durante a execução do Command definido.
Initial Directory Diretório que irá operar sobre esta configuração. Geralmente utilizamos o diretórios da própria aplicação corrente.
Use Output Window Marque está opção caso você deseje que o Visual Studio exiba o resultado dos comandos executados na janela de Output da IDE.
Prompt for arguments Marque está opção caso você deseje que o Visual Studio solicite os argumentos ao desenvolvedor.
Treat output as Unicode Marque está opção para exibir uma saída Unicode na janela de Output do Visual Studio.

Na janela de External Tools, vamos preencher no campo Title, um descritivo para identificarmos no menu do Visual Studio, que essa é a ferramenta do SubSonic, então preencha: "SubSonic Tool". No campo Command, vamos preencher o caminho do executável do SubSonic, no caso, este estará presente na pasta de instalação do SubSonic e encontra-se no caminho: "SubCommander\sonic.exe".

Feito isso, preencha o campo Arguments com o seguite valor: "generate /out App_Code/DAL/Generated", isto irá fazer com que o SubSonic gere dentro da pasta App_Code uma pasta chamada DAL, e dentro desta uma pasta chamada Generated, que irá conter todo o código gerado pela ferramenta.

E por último, em Initial directory, preencha com o valor: “$(ProjectDir)”, para indicar ao SubSonic que o código será tomado como base a partir do diretório da aplicação corrente. Ainda de forma opcional, você pode marcar ou desmarcar algumas opções nos checkboxes presentes nesta janela.

Vamos marcar a opção "Use Output window" para ver o resultado na janela de output e a opção "Prompt for arguments" para solicitar o argumento que preenchemos no campo "Arguments", caso queiramos mudar o caminho da geração de código. A Figura 1 demonstra como deve ficar a janela External tool, já preenchida.

Configurando SubSonic no Visual Studio 2008
Figura 1. Configurando SubSonic no Visual Studio 2008

Preparando uma base de dados

Já temos uma configuração inicial para o SubSonic e agora vamos desenvolver uma base de dados para exemplificar nosso modelo de aplicação. Neste artigo irei utilizar a base de dados MySQL, mas você pode utilizar os demais banco de dados suportados pelo SubSonic, tal como SQL Server, Oracle ou SQLite sem problemas. A Listagem 1, exibe um script para a criação de nossa base de dados no servidor MySQL.

Listagem 1.Script para criação das tabelas no banco de dados.

    --
    -- Create schema noticias
    --

    CREATE DATABASE IF NOT EXISTS noticias;
    USE noticias;

    --
    -- Definition of table `autores`
    --

    DROP TABLE IF EXISTS `autores`;
    CREATE TABLE `autores` (
    `Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `Nome` varchar(45) NOT NULL,
    `Telefone` varchar(20) NOT NULL,
    `Email` varchar(100) NOT NULL,
    PRIMARY KEY (`Id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

    --
    -- Dumping data for table `autores`
    --

    /*!40000 ALTER TABLE `autores` DISABLE KEYS */;
    /*!40000 ALTER TABLE `autores` ENABLE KEYS */;


    --
    -- Definition of table `categorias`
    --

    DROP TABLE IF EXISTS `categorias`;
    CREATE TABLE `categorias` (
    `Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `Descricao` varchar(45) NOT NULL,
    PRIMARY KEY (`Id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

    --
    -- Dumping data for table `categorias`
    --

    /*!40000 ALTER TABLE `categorias` DISABLE KEYS */;
    /*!40000 ALTER TABLE `categorias` ENABLE KEYS */;


    --
    -- Definition of table `noticias`
    --

    DROP TABLE IF EXISTS `noticias`;
    CREATE TABLE `noticias` (
    `Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `Titulo` varchar(45) NOT NULL,
    `SubTitulo` varchar(45) NOT NULL,
    `Conteudo` text NOT NULL,
    `IdAutor` int(10) unsigned NOT NULL,
    `IdCategoria` int(10) unsigned NOT NULL,
    PRIMARY KEY (`Id`),
    KEY `FK_noticia_autor` (`IdAutor`),
    KEY `FK_noticia_categoria` (`IdCategoria`),
    CONSTRAINT `FK_noticia_autor` FOREIGN KEY (`IdAutor`) REFERENCES `autores` (`Id`),
    CONSTRAINT `FK_noticia_categoria` FOREIGN KEY (`IdCategoria`) REFERENCES `categorias` (`Id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    

Como podemos ver neste Script da Listagem 1, temos uma base de dados que irá representar um sistema de notícias, separando as notícias por Autor e Categoria. Repare que cada tabela do nosso banco de dados contém uma chave-primária.

Além das questões naturais de normalização das tabelas, também é um padrão para o SubSonic, que obrigatoriamente impõe a regra de que cada tabela deve conter uma chave-primária, para que no momento da geração de código ele consiga fazer métodos precisos para trabalhar diretamente com o registro em questão, tal como exclusões, seleções únicas, atualizações e seleções de modo geral.

Configurando nossa aplicação de Exemplo

Feito isso, temos o SubSonic configurado no Visual Studio, e uma base de dados de exemplo para fazermos alguns testes. Agora, vamos iniciar um novo WebSite no Visual Studio. Para isso vá ao menu File>New>WebSite. Na janela de projetos selecione o template WebSite, especifique a linguagem que irá utilizar, o caminho que irá armazenar seu aplicativo de exemplo e clique em OK.

Agora vamos configurar nossa aplicação para funcionar junto com o SubSonic. Primeiramente devemos adicionar uma referência aos componentes do SubSonic. Para isso vá até o menu WebSite do Visual Studio, clique em Add Reference e clique na guia Browser para localizar e adicionar a referência.

Vamos selecionar dois arquivos, o primeiro deles é o SubSonic.dll que se localiza na pasta de instalação do SubSonic. E o segundo é a dll do MySQL (MySql.Data.dll) que o SubSonic utiliza para fazer o acesso aos dados. Ambos localizam-se na pasta SubSonic dentro da pasta de instalação da ferramenta. Através da guia Browse, navegue até esta pasta, selecione ambos os arquivos e clique em OK.

Com isso já podemos configurar nossa aplicação para que o SubSonic gere as classes para nossa camada de acesso a dados. Abra o arquivo web.config e adicione as linhas da Listagem 2 para que o .NET Framework nos permita adicionar uma sessão no web.config própria do SubSonic, que irá definir algumas configurações para fazer a geração automática de código.

Listagem 2. Configurando a ferramenta na aplicação.

    <configSections>
    <section name="SubSonicService" type="SubSonic.SubSonicSection, SubSonic"/>
    </configSections>
    

Vamos agora, adicionar uma string de conexão para que o SubSonic possa conectar-se com nossa base de dados, para conseguir ler o modelo do banco e gerar o código. A Listagem 3 exibe uma string de conexão para nosso banco de exemplo do MySQL. Lembre-se de configurar corretamente o seu respectivo login e senha para acesso ao banco.

Listagem 3. String de conexão para nossa base de dados de exemplo.

    <connectionStrings>
    <add name="NoticiasConnectionString" connectionString="server=127.0.0.1;user
    id=root;Password=****;database=noticias" providerName="MySql.Data.MySqlClient"/>
    </connectionStrings>
    

Devemos agora adicionar na seção do SubSonic, que foi configurada na Listagem 2, qual será o provider padrão que iremos utilizar nesta aplicação, bem como o assembly e a string de conexão para nossa base de dados.

Opcionalmente, também vamos definir o nome de um namespace para termos uma organização em nosso código gerado. A Listagem 4 exibe como devemos fazer essa configuração dentro do nó Configuration.

Listagem 4. Definições de configuração do SubSonic.

    <SubSonicService defaultProvider="NoticiasMySql">
    <providers>
    <add name="NoticiasMySql" type="SubSonic.MySqlDataProvider, SubSonic"
    connectionStringName="NoticiasConnectionString" generatedNamespace="Noticias.DAL"/>
    </providers>
    </SubSonicService>
    

Como podemos ver na Listagem 4, adicionamos o nó SubSonicService e definimos um provider padrão chamado NoticiasMySql. Em seguida na tag <providers>, adicionamos este provider definido como padrão pelo atributo name (NoticiasMySql).

No atributo type definimos que utilizaremos a classe SubSonic.MySqlDataProvider (dentro do Assembly SubSonic), sendo que a string de conexão é a mesma que foi definida na Listagem 3, como NoticiaConnectionString. E por fim, definimos um nome para nosso namespace do código gerado, que será Noticias.DAL.

Com isso, temos nossa aplicação já está devidamente configurada para a geração de código pelo SubSonic. Apesar de ser um pouco trabalhoso fazer estas configurações, teremos um ganho em relação a produtividade.

Desenvolvendo uma aplicação com SubSonic

Agora que temos nossa IDE de desenvolvimento e nossa aplicação configurada, vamos executar a utilização do SubSonic. Para isso, no menu Tools selecione o item criado "SubSonic Tool". Caso você tenha deixado a opção "Prompt for Arguments" ativada, irá surgir uma janela que é exibida aqui na Figura 2.

Solicitação de parâmetros para execução
Figura 2. Solicitação de parâmetros para execução

É importante salientar que toda vez que fizermos a geração de código pela ferramenta configurada no Visual Studio, o SubSonic irá sobrepor a última geração de código feita. Ou seja, toda vez que você alterar sua base de dados você deve fazer uma nova geração para atualizar as classes, mantendo sua camada de acesso a dados equivalente com a estrutura do seu banco de dados.

Lembre-se que você pode customizar as classes geradas pela ferramenta, pois todas estas são geradas como "partial class". E sendo assim, você pode separar os códigos em arquivos diferentes não perdendo sua customização em uma próxima execução da ferramenta.

Para continuarmos, clique em OK para confirmar o caminho solicitado, e você verá na janela de output do Visual Studio que a ferramenta foi executada com sucesso. A Figura 3 exibe a execução com sucesso da ferramenta.

Execução com sucesso do SubSonic.
Figura 3. Execução com sucesso do SubSonic.

Agora, clique no botão direito sobre a Solução na Solution Explorer, e escolha a opção Refresh. Observe na própria Solution Explorer que dentro da pasta App_Code\DAL\Generated, temos todas as nossas classes de acesso a dados criadas. Confira na Figura 4.

Solution Explorer de nosso projeto.
Figura 4. Solution Explorer de nosso projeto

Abra o arquivo Categoria.cs e veja as duas classes que foram geradas: Categoria e CategoriaCollection. A primeira é a classe que representa um registro da tabela de categorias, e a segunda é a classe que representa uma coleção de categorias.

Como são classes geradas pelo SubSonic, elas fazem uso de diversos recursos da ferramenta, inclusive herdando de classes do namespace SubSonic. A classe Categoria é bem completa e não é possível mostrá-la integralmente aqui neste artigo, mas só para você ter uma idéia vou colocar aqui na Listagem 5, alguns trechos importantes dessa classe, apenas para observarmos como o Subsonic às cria.

Listagem 5. Trechos da classe Categoria


    /// <summary>
    /// This is an ActiveRecord class which wraps the categorias table.
    /// </summary>
    [Serializable]
    public partial class Categoria : ActiveRecord<Categoria>, IActiveRecord
    {
    #region .ctors and Default Settings

    public Categoria()
    {
    SetSQLProps();
    InitSetDefaults();
    MarkNew();
    }

    private void InitSetDefaults() { SetDefaults(); }

    public Categoria(bool useDatabaseDefaults)
    {
    SetSQLProps();
    if(useDatabaseDefaults)
    ForceDefaults();
    MarkNew();
    }

    ...

    protected static void SetSQLProps() { GetTableSchema(); }

    #endregion

    ...

    private static void GetTableSchema()
    {
    if(!IsSchemaInitialized)
    {
    //Schema declaration
    TableSchema.Table schema = new TableSchema.Table("categorias",
    TableType.Table, DataService.GetInstance("NoticiasMySql"));
    schema.Columns = new TableSchema.TableColumnCollection();
    schema.SchemaName = @"";
    //columns

    TableSchema.TableColumn colvarId = new
    TableSchema.TableColumn(schema);
    colvarId.ColumnName = "Id";
    colvarId.DataType = DbType.Int32;
    colvarId.MaxLength = 0;
    colvarId.AutoIncrement = true;
    colvarId.IsNullable = false;
    colvarId.IsPrimaryKey = true;
    colvarId.IsForeignKey = false;
    colvarId.IsReadOnly = false;
    colvarId.DefaultSetting = @"";
    colvarId.ForeignKeyTableName = "";
    schema.Columns.Add(colvarId);

    TableSchema.TableColumn colvarDescricao = new
    TableSchema.TableColumn(schema);
    colvarDescricao.ColumnName = "Descricao";
    colvarDescricao.DataType = DbType.String;
    colvarDescricao.MaxLength = 45;
    colvarDescricao.AutoIncrement = false;
    colvarDescricao.IsNullable = false;
    colvarDescricao.IsPrimaryKey = false;
    colvarDescricao.IsForeignKey = false;
    colvarDescricao.IsReadOnly = false;
    colvarDescricao.DefaultSetting = @"";
    colvarDescricao.ForeignKeyTableName = "";
    schema.Columns.Add(colvarDescricao);

    BaseSchema = schema;
    //add this schema to the provider
    //so we can query it later

    DataService.Providers["NoticiasMySql"].
    AddSchema("categorias",schema);
    }
    }
    #endregion
    ...

    #region Props

    [XmlAttribute("Id")]
    [Bindable(true)]
    public int Id
    {
    get { return GetColumnValue<int>(Columns.Id); }
    set { SetColumnValue(Columns.Id, value); }
    }

    [XmlAttribute("Descricao")]
    [Bindable(true)]
    public string Descricao
    {
    get { return GetColumnValue<string>(Columns.Descricao); }
    set { SetColumnValue(Columns.Descricao, value); }
    }

    #endregion

    ...
    }
    

Como você pode notar, só foram listados aqui os Construtores da Classe, e suas propriedades. Note, como foi dito anteriormente, que a classe Categoria herda da classe ActiveRecord<T> e também implementa a interface IactiveRecord, ambos integrantes do namespace SubSonic. O interessante é que como o SubSonic é um projeto de código aberto, você pode verificar o conteúdo dessas classes e ver exatamente como funcionam.

Dentro da classe Categoria foi listado aqui apenas um dos vários construtores que foram criados na classe. O interessante aqui é que o construtor chama o método SetSQLProps(), que por sua vez chama o método GetTableSchema(), que podemos conferir sua implementação logo abaixo.

Veja que é neste método que temos a definição da estrutura da tabela Categoria, que foi recuperada do banco de dados, através do SubSonic. É neste método que temos o mapeamento entre a classe Categoria e sua respectiva tabela no MySQL. Mais a baixo você vai ver a implementação das propriedades Id e Descricao, que representam as colunas de mesmo nome na tabela de categorias.

Como podemos ver o SubSonic é uma ferramenta que gera as classes que fazem o mapeamento objeto-relacional entre nossa aplicação e o banco de dados. Uma característica importante do SubSonic é que ele depende da existência de um banco de dados, criando o todo mapeamento com base nessa estrutura já existente. Diferente de outras ferramentas de ORM, como por exemplo o NHibernate e o ADO.NET Entity Framework 4.0, que permitem o desenvolvimento do Modelo de classes antes do database. Na sequência vamos ver como utilizar as classes que foram geradas, para criar nossas aplicações Web.

Nota do DevMan

Algumas das soluções que se destinam a fazer a interface entre aplicações desenvolvidas com a Orientação a Objetos e Bancos de Dados relacionais, são conhecidas como Ferramentas de Mapeamento Objeto Relacional (O/RM).

O Mapeamento objeto/relacional é uma técnica que visa a redução da incompatibilidade que existe entre a programação orientada a objetos e os bancos de dados relacionais. Com o mapeamento, as tabelas do banco de dados são representadas através de classes, e os registros são os objetos instanciados das classes correspondentes.

Em tese, com a utilização de uma feramenta O/RM, o programador não precisa escrever comandos na linguagem SQL. A linguagem utilizada para o acesso e armazenamento das informações é orientada a objetos.

Nem todas as ferramentas que se destinam a resolver o problema de incompatibilidade da OO com os databases relacionais são O/RMs, mas todas acabam oferencendo o mesmo resultado final.

Segue abaixo uma lista de Ferramentas que tem o objetivo de reduzir a incompatibilidade entre OO e databases relacionais (dentre elas algumas são O/RMs). As três primeiras em destaque são as mais popularmente utilizadas.

  • SubSonic: Foco principal deste artigo, o SubSonic é uma ferramenta ORM que depende da existência de uma estrutura de banco de dados. Através de um aplicativo externo que rodamos no Visual Studio, o SubSonic lê a estrutura de tabelas do banco e cria todo o modelo de classes que irá fazer o acesso e persistência dos dados no database.
  • ADO.NET Typed Datasets: Ferramenta nativa do ADO.NET desde a versão 1.1, porém só a partir da versão 2.0 do framework que veio com os TableAdapters, que permitem o mapeamento entre Métodos e Comandos SQL.
  • NHibernate: Uma ferramenta de código aberto que faz mapeamento objeto relacional para .NET. Com ela você faz o mapeamento em arquivos XML, e todos os comandos SQL são gerados em tempo de execução. É compatível com a grande maioria de databases relacionais existentes no mercado.
  • ADO.NET Entity Framework: Mais nova ferramenta da Microsoft destinada ao mapeamento objeto/relacional. Introduz o conceito de Entidades, e é compatível com vários databases. Gera os comandos SQL em tempo de execução e é totalmente compatível com a linguagem LINQ para a construção de queries.
  • LLBLGen Pro
  • DataObjects.NET
  • Data Tier Modeler for .NET (DTM)
  • eXpress Persistent Objects for .NET
  • Eldorado.NET
  • Entity Broker
  • JC O/R Framework & AtomsFramework
  • Nolics.NET
  • Norpheme
  • ObjectBroker
  • ObjectSpark
  • Objectz.NET
  • DomainObjects for .NET (antigo OJB.NET)
  • OPF.NET
  • ORM.NET
  • Genome

Note que estas são apenas algumas ferramentas com este propósito. Se você pesquisar mais a fundo, certamente irá encontrar muitas outras.

Operações CRUD com SubSonic

Abra seu WebForm Default.aspx, e neste adicione uma Gridview simples e nomeando-a para gridCategorias. Esta grid servirá para fazermos uma exibição tabular de nossos dados. Em seguida abra o Code Behind, inclua o namespace gerado pelo SubSonic, e digite o código da Listagem 6.

Listagem 6. Listagem simples de dados.

    using Noticias.DAL;

    public partial class _Default : System.Web.UI.Page
    {
    private void ExibirCategorias()
    {
    // retorna um DataSet do banco de dados
    var categorias = DB.Select().From(Tables.Categoria).ExecuteDataSet();

    //exibe os dados na GridView
    gridCategorias.DataSource = categorias;
    gridCategorias.DataBind();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    ExibirCategorias();
    }
    }
    }
    

Como podemos ver, escrevemos um código semelhante à linguagem que estamos acostumados a utilizar no SQL. Com tudo isso, o SubSonic será capaz de interpretar e gerar o comando SQL necessário para ser executado em nossa base de dados, e trazer os dados na forma de um DataSet, já preenchido com o resultado deste comando.

A partir da classe DB, e do método Select, faça uma navegação para se familiarizar com os métodos dessa poderosa ferramenta, eveja que os métodos são bem semelhantes a comandos SQL e no final de tudo, você consegue executar este comando como um DataSet, DataReader, List<T> (Lista genérica que nos fornece um resultado fortemente tipado), entre outros métodos.

Insira alguns dados em sua base de dados na tabela Categoria, e execute nossa aplicação de exemplo para verificar a exibição dos dados em nossa Gridview.

Agora vamos ver como inserir e atualizar dados em nossa tabela no banco de dados. Para isso no WebForm Default.aspx insira uma Textbox, um RequiredFieldValidator para obrigar o usuário a informar o campo, e um button para salvar os dados no formulário. Vamos também personalizar nossa Gridview para termos uma flexibidade maior quando excluirmos um dados. A Listagem 7, exibe como o código do webform deve ficar para atender essas necessidades do exemplo.

Listagem 7.WebForm de exemplo.

    <fieldset>
    <legend>[ Nova Categoria ]</legend>

    Descrição:
    <asp:TextBox ID="txtDescricao"
    runat="server"
    MaxLength="45"
    Columns="30">
    </asp:TextBox>
    <br />

    <asp:RequiredFieldValidator ID="rfvDescricao"
    runat="server"
    ControlToValidate="txtDescricao"
    SetFocusOnError="true"
    Display="Dynamic"
    ErrorMessage="Informe a descrição da categoria"
    ValidationGroup="validacaoCategoria">
    </asp:RequiredFieldValidator>
    <br />

    <asp:Button ID="btnSalvar"
    runat="server"
    Text="Salvar"
    ValidationGroup="validacaoCategoria"
    onclick="btnSalvar_Click" />

    </fieldset>
    <hr />

    <asp:GridView ID="gridCategorias"
    runat="server"
    AutoGenerateColumns="false"
    DataKeyNames="Id">
    <Columns>
    <asp:BoundField DataField="Descricao" HeaderText="Descrição" />
    <asp:TemplateField>
    <ItemTemplate>
    <asp:LinkButton ID="lnkDelete"
    runat="server"
    Text="Excluir"
    CommandName="Delete"
    OnClientClick="return confirm('Deseja
    excluir esta categoria ?');">
    </asp:LinkButton>
    </ItemTemplate>
    </asp:TemplateField>
    </Columns>
    </asp:GridView>
    

Veja que além da adição do nosso formulário, temos também a Gridview mais personalizada. Note que a propriedade AutoGenerateColumns foi definida como false, para que a Gridview não gere as colunas automaticamente no momento do Bind dos dados. Também temos também a propriedade DataKeyNames definida como Id, informando a Gridview que o campo Id da fonte de dados será o campo chave para a listagem dos dados. Feito isso, adicionamos a coluna Descricao e uma coluna do tipo TemplateField para incluirmos um linkbutton para fazermos a exclusão do registro. No formulário de inclusão de registro, estamos utilizando grupos de validação. Caso você queira definir mais algum formulário neste mesmo webform, poderá separar a validação de cada um deles. Agora, no modo Design do Visual Studio, de um duplo clique no button btnSalvar para criarmos um evento click, para definirmos como será o código de inserção de dados. Neste evento, adicione o código da Listagem 8.

Listagem 8. Inserção e Atualização de dados na tabela do banco de dados.

    protected void btnSalvar_Click(object sender, EventArgs e)
    {
    //verificamos se a página está válida (pelo validators)
    //isso é uma boa prática para forçarmos a validação no Servidor.
    if (Page.IsValid)
    {
    //cria um objeto Categoria da namespace gerada pelo SubSonic
    Categoria c = new Categoria();

    //caso fosse uma atualização de dados, você poderia chamar
    //o método abaixo comentado para carregar os dados e definir o Id
    //do registro a ser atualizado
    //c.LoadByKey(Id);

    //setamos os valores nas propriedades do objeto
    //neste caso só temos uma propriedade
    c.Descricao = txtDescricao.Text;

    //como é um registro novo, definimos essa propriedade como true
    //caso seja um registro existente, definimos essa como false.
    c.IsNew = true;

    //executamos o método save que irá executar o comando preparator
    //internamente pelo SubSonic
    c.Save();


    //exibe as categorias novamente
    ExibirCategorias();
    }
    } 

Execute a aplicação, e adicione algumas categorias na listagem. Veja o resultado na Figura 5. Como podemos ver, o SubSonic nos fornece uma grande flexibilidade e um modelo de acesso a dados bem elegante e de fácil entendimento para manipulações.

Testando aplicação criada com SubSonic
Figura 5. Testando aplicação criada com SubSonic

Para fazer exclusões, o SubSonic gera para cada classe um método static (shared em VB.NET) chamado Delete. Este método recebe a chave-primária da tabela e executa a exclusão do registro no banco de dados.

Para adicionarmos um comando neste exemplo para fazermos exclusões, no modo Design do Visual Studio, selecione a Gridview e na janela de propriedades clique no botão de Evento (aquele pequeno raio na parte superior da janela de propriedades), e de um duplo clique no evento RowDeleting. A Listagem 9, exibe como seria uma exclusão simples de registro da nossa tabela de categoria aplicada ao evento RowDeleting de nossa Gridview. Execute novamente a aplicação de exemplo, e veja como a exclusão dos registros ficou simples e de fácil implementação.

Listagem 9. Exclusão de um registro pelo evento RowDeleting

    protected void gridCategorias_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
    //exclui a categoria indicada
    Categoria.Delete(gridCategorias.DataKeys[e.RowIndex].Value);

    //exibe as categorias novamente
    ExibirCategorias();
    }
    

Nota do DevMan

O evento RowDeleting da Gridview, ocorre quando um registro está sendo excluído. Através do parâmetro 'e' do tipo GridviewDeleteEventArgs, é que conseguimos resgatar alguns valores como o índice a linha no Gridview que está sendo processada.

Através desse evento temos ainda a possibilidade de cancelar a exclusão, entre outras possibilidades. Outro evento relacionado a este é o RowDeleted que ocorre depois que uma exclusão foi executada; neste evento conseguimos recuperar se a exclusão foi executada com sucesso ou não.

Conclusão

Vimos neste artigo como é possível de uma forma bem fácil, configurar o SubSonic no Visual Studio e em nossa aplicação, para a utilização dessa poderosa ferramenta de ORM (Mapeamento Objeto/Relacional).

Há muito que ser explorado no Subsonic, como por exemplo, fazer consultas mais personalizadas, aplicar controle transacional nas operações, entre outras funcionalidades que essa ferramenta nos possibilita.

Esta é apenas uma das demais alternativas no quesito de escolha de ferramentas para geração de código e auxílio, pois existem muitas outras como NHibernate, LINQ To SQL, Entity Framework, etc. Cada ferramenta contém suas particularidades e fica a gosto do desenvolvedor escolher dentre estas qual seria a melhor opção para sua aplicação.

Confira também