ASP .NET- Trabalhando em camadas com o ObjectDataSource


Se você tem acompanhado meus artigos recentemente deve ter notado que eu não me canso de escrever sobre como criar aplicações em camadas.

Além de ser uma prática recomendada e de lhe permitir criar aplicações mais escaláveis e mais fáceis de testar, o seu código fica mais limpo e mais fácil de manter.

Você já deve ter percebido que existem diversas formas de criar aplicações em camadas e hoje eu vou mostrar como fazer isso usando o ObjectDataSource da ASP .NET.

Se você não lembra, o ObjectDataSource é um dos controles para acesso a dados existentes na guia Data da ToolBox do Visual Studio ou Visual Web Developer.

Ele fornece acesso à um determinado método de uma alguma classe. Estas classes geralmente encapsulam o acesso à base de dados, ou qualquer repositório, retornando uma coleção de objetos que deve ser apresentada ao usuário. para uma camada intermediária como uma camada de acesso a dados ou um componente de negócio.

Como eu já escrevi muito sobre o assunto, neste artigo vou recordar a utilização deste recursos em uma aplicação ASP .NET usando o Visual Web Developer 2010 Express Edition e o SQL Server 2008 Express de uma forma mais objetiva.

Abaixo vemos a figura que representa o um exemplo de arquitetura em camadas usando o ObjectDataSource, onde você pode ver que o controle serve como uma interface entre os controles de dados vinculados da camada de apresentação e as classes de acesso a dados na camada do meio.

É óbvio que este modelo não é o mais otimizado mas já é um avanço e podemos usá-lo em algumas ocasiões para aplicações mais simples.

Vamos direto ao exemplo prático de como usar o ObjectDataSource em uma aplicação ASP .NET com uma classe de acesso a dados.

Vamos criar uma página que permite exibir uma relação de produtos com opção para filtrar por categoria de produto, um exemplo bem simples e recorrente.

Vou usar o banco de dados Northwind.mdf do SQL Server e trabalhar com as tabelas Products e Categories que possuem a seguinte estrutura:

Abra o Visual Basic 2010 Express Edition e crie um novo projeto do tipo ASP .NET Empty Web Application com o nome ListaProdutos:

Inclua um novo WebForm (menu Project -> Add New Item) com o nome Default.aspx no projeto.

Agora no menu Project -> Add Class inclua uma classe com o nome ProdutoDAL.vb;

Vamos definir o código da classe ProdutoDAL.vb com 3 métodos estáticos (Shared) :

Imports System.ComponentModel
Imports System.Data
Imports System.Data.SqlClient
/
<DataObject(True)>
Public Class Produtos

    <DataObjectMethod(DataObjectMethodType.Select)>
    Public Shared Function GetTodasCategorias() As IEnumerable
        Dim con As New SqlConnection(GetConnectionString)
        Dim sel As String = "SELECT CategoryID, CategoryName " &
                                     "FROM Categories ORDER BY CategoryName"
        Dim cmd As New SqlCommand(sel, con)
        con.Open()
        Dim rdr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
        Return rdr
    End Function

    <DataObjectMethod(DataObjectMethodType.Select)>
    Public Shared Function GetProdutosPorCategoria(ByVal categoryID As String) As IEnumerable
        Dim con As New SqlConnection(GetConnectionString)

        Dim sel As String = "SELECT ProductID, ProductName, UnitPrice FROM Products " &
                                     "WHERE CategoryID = @CategoryID ORDER BY ProductID"

        Dim cmd As New SqlCommand(sel, con)
        cmd.Parameters.AddWithValue("CategoryID", categoryID)
        con.Open()
        Dim rdr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
        Return rdr
    End Function

    Private Shared Function GetConnectionString() As String
        Return ConfigurationManager.ConnectionStrings("MacorattiConnectionString").ConnectionString
    End Function

End Class

Estamos usando os namespaces System.Data e System.Data.SqlClient para acessar o banco de dados SQL Server.

Definimos instruções SQL do tipo SELECT para obter os dados das tabelas Products e Categories.

A segunda consulta usa o parâmetro CategoryID para filtrar os produtos por Categoria.

Como não estamos realizando atualizações na tabela estamos trabalhando com um objeto DataReader.

Note que estamos usando os atributos DataObject e DataObjectMethod na definição dos métodos.

Os atributos são uma forma de declarar informação para uma classe, métodos, etc. Eles não são obrigatórios e são usados apenas para ajudar o assistente de configuração a reconhecer os métodos das classes de acesso a dados.

Vamos definir a string de conexão no arquivo Web.Config conforme abaixo:

<?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <connectionStrings>
    <add name="MacorattiConnectionString" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0"/>
  </system.web>
</configuration>

A string de conexão esta sendo obtida usando o ConfigurationManager:

A classe ConfigurationManager é uma nova classe que permite o acesso de forma programática ao arquivo de configuração e suas seções. Podemos destacar as seguintes funcionalidades desta classe.

A seguir temos os principais métodos e propriedades da classe ConfigurationManager:

Propriedade\Método Descrição
AppSettings Obtêm os dados da seção <appSettings> do arquivo de configuração da aplicação.
ConnectionStrings Obtêm os dados da seção <ConnectionStrings> do arquivo de configuração da aplicação.
OpenExeConfiguration Abre o arquivo de configuração cliente especificado com um objeto.
OpenMachineConfiguration Abre o arquivo de configuração machine especificado com um objeto
OpenWebConfiguration Abre o arquivo de configuração da aplicação web especificado com um objeto.

Para dar uma aparência mais suave a nossa página Defaut.aspx vamos incluir um arquivo de estilo (.css).

No menu Project-> Add New Item selecione o template Style Sheet e informe o nome Estilo.css

A seguir defina o código abaixo para definir o estilo neste arquivo:

body {
    font-family: Verdana, Helvetica, Sans-Serif;
    font-size: 85%;
    margin: 0;
    padding: 0;
    background-color: #d3d3d3;
}
p 
{
    margin-top: 15px;
    margin-bottom: 20px;
}
#page 
{
    width: 800px;
    margin: 0 auto;
    background-color: White;
}
#header
{
    margin-bottom: 0;
}
#main
{
    padding: 10px;
    margin-top: 0;
}
#ddlCategoria
{
    width: 150px;
}
#ddlProdutos
{
    color: #000000;
    background-color: #FFFFFF;
    border: 1px solid #999999;
    
}
.col1
{
    width: 100px;
}
.col2
{
    width: 200px;
}
.col3
{
    width: 100px;
    text-align: right;
}
	

Para podermos usar este arquivo de estilo temos que definir entre as tags head da página Default.aspx o seguinte código:

<style type="text/css">
   <link href="Estilo.css" rel="stylesheet" type="text/css" />
</style>

Vamos agora definir o leiaute da nossa página Default.aspx a qual conterá os seguintes controles:

O dropdownlist ddlCategoria será vinculado ao controle ObjectDataSource1 que retorna uma lista de todas a categorias;

O controle DataList será vinculado ao controle ObjectDataSource2 que usa uma consulta parametrizada para retornar os produtos para uma categoria selecionada. O parãmetro CategoryID é obtido do controle ddlCategoria a partir da propriedade SelectedValue;

Ambos os controles ObjectDataSource utilizam a classe Produtos que contém métodos Shared que retorna as categorias e os produtos por categoria;

No controle DataList definimos um ItemTemplate para exibir os valores das colunas da tabela Products em uma tabela HTML definida no HeaderTemplate;

O código completo da Página Default.aspx pode ser vista abaixo:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Lista de Produtos</title>
    <style type="text/css">
        </style>
    <link href="Estilo.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div id="page">
        <div id="header">
            <asp:Image ID="Image1" runat="server" ImageUrl="~/maco10.gif" />
        </div>
        <div id="main">
            <p>
                Escolha uma Categoria:&nbsp;
                <asp:DropDownList ID="ddlCategoria" runat="server" 
                    DataSourceID="ObjectDataSource1" DataTextField="CategoryName" DataValueField="CategoryID" AutoPostBack="True">
                </asp:DropDownList>
                <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"  SelectMethod="GetTodasCategorias" TypeName="ListaProdutos.Produtos">
                </asp:ObjectDataSource>
            </p>
            <asp:DataList ID="dlProdutos" runat="server" 
                DataSourceID="ObjectDataSource2" CellPadding="3" GridLines="Vertical">
                <HeaderTemplate>
                    <table>
                        <tr>
                            <td class="col1">Código</td>
                            <td class="col2">Produto</td>
                            <td class="col3">Preço</td>
                        </tr>
                    </table>
                </HeaderTemplate>
                <ItemTemplate>
                    <table>
                        <tr>
                            <td class="col1">
                                <asp:Label ID="lblID" runat="server" 
                                    Text='<%# Eval("ProductID") %>' />
                            </td>
                            <td class="col2">
                                <asp:Label ID="lblName" runat="server" 
                                    Text='<%# Eval("ProductName") %>' />
                            </td>
                            <td class="col3">
                                <asp:Label ID="lblUnitPrice" runat="server" 
                                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
                            </td>
                        </tr>
                    </table>
                </ItemTemplate>
                <AlternatingItemStyle BackColor="#CCCCCC" />
                <HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />
            </asp:DataList>
            <asp:ObjectDataSource ID="ObjectDataSource2" runat="server" 
                SelectMethod="GetProdutosPorCategoria" TypeName="ListaProdutos.Produtos"  OldValuesParameterFormatString="">
                <SelectParameters>
                    <asp:ControlParameter ControlID="ddlCategoria" Name="CategoryID"  PropertyName="SelectedValue" Type="String" />
                </SelectParameters>
            </asp:ObjectDataSource>
        </div>
    </div>
    </form>
</body>
</html>

Executando o projeto iremos obter:

Pegue o projeto completo aqui: ListaProdutos.zip

"E ele lhes disse: Na verdade vos digo que ninguém há , que tenha deixado casa, ou pais, ou irmãos, ou mulher, ou filhos, pelo reino de Deus, e não haja de receber muito mais neste mundo, e na idade vindoura a vida eterna." Lucas 18:29-30

Referências:


José Carlos Macoratti