Livros publicados:

 

 

 

         Bom, meu objetivo Ă© mostrar como criar de uma nova forma cache de acesso a dados com pool de conexĂ”es. Com o uso da internet e as facilidades que a mesma atribui a todos que a utilizam, surgiu outra preocupação com softwares e sites dinĂąmicos, acesso a banco de dados, nĂșmero de pessoas que acessam sistemas pela internet. A rapidez das informaçÔes mostradas ao cliente conta muito para que haja confiança e credibilidade pela parte do usuĂĄrio.

 

         Imagine uma pessoa acessando ao site que automaticamente busca a informação do banco de dados, nĂŁo importa qual banco. Um cliente acessando o banco de dados Ă© bem tranqĂŒilo, agora imagine 10.000 clientes ao mesmo tempo acessando o mesmo site de notĂ­cias ou de venda de produtos. Se o software desenvolvido nĂŁo foi preparado para essa quantidade de pessoas acessando ao mesmo momento, pode ocorrer um risco de travar ou elevar o nĂ­vel de processamento e memĂłria do servidor, ou seja, caso nĂŁo tratado de uma forma correta, pool de conexĂ”es ou aproveitamento de conexĂŁo jĂĄ criada, pode demorar por demais mostrar ao usuĂĄrio ou cliente a notĂ­cia ou produto. Quem perde Ă© vocĂȘ dono do site ou empreendimento de vendas, nos dias de hoje os usuĂĄrios jĂĄ nĂŁo tĂȘm muita paciĂȘncia para esperar muito tempo, isso Ă© um erro muito grave junto aos jovens, crianças e adultos; nĂŁo saber esperar 30 segundos, 10 segundos, o que seja.

 

ReferĂȘncias necessĂĄrias:

 

- Framework 2.0;

- Visual Studio .NET 2005;

- Sql Express 2005;

- Linguagem C#.NET;

- Imagine que um projeto do tipo WEB jĂĄ esteja criado.

 

         A criação de cache e pool de conexĂŁo para a versĂŁo 2005 da IDE Visual Studio .NET estĂĄ mais robusta e eficaz do que a versĂŁo anterior. O arquivo web.config jĂĄ estĂĄ preparado para a funcionalidade. O primeiro de tudo Ă© criar e configurar o caching. ReferĂȘncia 1.1.

 

Arquivo WEB.CONFIG

 

<connectionStrings>

    <add name="SiteDB" connectionString="Data Source=.\SQLEXPRESS;

      Integrated Security=True; User Instance=True;

      AttachDBFilename=|DataDirectory|\AspNetDB.mdf;"

      providerName="System.Data.SqlClient"/>

</connectionStrings>

 

<system.web>

    <caching>

      <sqlCacheDependency enabled="true" pollTime="10000">

        <databases>

          <add name="siteDB" connectionStringName="SiteDB" pollTime="2000"/>

        </databases>

      </sqlCacheDependency>

    </caching>

</system.web>

 

ReferĂȘncia: 1.1

 

Explicação:

 

A primeira tag <connectionStrings> Ă© a nova forma utilizada para conexĂŁo com banco de dados sql express 2005. O nome do banco de dados criado Ă© ASPNETDB.mdf. O nome “SiteDB” Ă© para referenciĂĄ-lo dentro do cĂłdigo C#.NET a string de conexĂŁo.

 

 

    <caching>

      <sqlCacheDependency enabled="true" pollTime="10000">

        <databases>

          <add name="siteDB" connectionStringName="SiteDB" pollTime="2000"/>

        </databases>

      </sqlCacheDependency>

    </caching>

 

ReferĂȘncia: 1.2

 

A tag estĂĄ localizada dentro da <system.web> logo apĂłs do fecho </connectionStrings>. Habilito o sqlCacheDependecy com o pollTime igual a 10000. Abri uma outra tag chamada <databases> onde defino qual a conexĂŁo do banco de dados utilizar com um pollTime especĂ­fico a ele.

 

 

 

<add name="siteDB" connectionStringName="SiteDB" pollTime="2000"/>

 

ReferĂȘncia: 1.3

 

 

         Na referĂȘncia 1.3, adicionei um nome “siteDB” minĂșsculo onde indico a connectionStringName referenciada na string de conexĂŁo anteriormente, ou seja, a que estĂĄ dentro da <connectionStrings>. O atributo connectionStringName possui o mesmo nome da connectionString, isso significa que foi referenciado qual o pool escolhido para determinado banco de dados. Essa nova funcionalidade Ă© legal porque posso referencia ou colocar quantos bancos de dados quiser para dentro da aplicação. Grave bem o atributo name adicionado de forma minĂșscula, usarei em breve dentro do cĂłdigo para fazer o caching.

 

         Depois de configurado no web.config vou direto para o banco de dados definir tabela e campos. ReferĂȘncia 1.4.

 

 

 

ReferĂȘncia: 1.4

 

No banco de dados defini apenas dois campos como na figura de referĂȘncia 1.4. NĂŁo esqueça de colocar o campo ID como auto-incremento. O campo CustomerName Ă© do tipo nvarchar e do tamanho de 100 caracteres, ou seja, serve apenas para colocar o nome.

 

Este banco foi criado utilizando a IDE Visual Studio.NET 2005 pela aba SOLUTION EXPLORER. (ReferĂȘncia 1.5)

 

 

 

ReferĂȘncia: 1.5

 

         Depois de criado o banco de dados, populei alguns dados.

 

 

Codificando cĂłdigo na classe

 

 

         Cliquei com o botĂŁo direito do mouse em cima do projeto e adicionei um novo item cujo o “template” Ă© o “Class”. Coloquei o nome de CustomerDetails.cs que ficou dentro da pasta APP_CODE. Dentro da classe adicionei apenas Get e Set dos campos criados no banco de dados, ou seja, mapeamento do banco de dados. ReferĂȘncia 1.6

 

 

 

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

 

/// <summary>

/// Summary description for CustomerDetails

/// </summary>

public class CustomerDetails

{

      public CustomerDetails()

      {

            //

            // TODO: Add constructor logic here

            //

      }

 

    private int _id;

    private string _customerName;

 

    public string CustomerName

    {

        get { return _customerName; }

        set { _customerName = value; }

    }

 

    public int Id

    {

        get { return _id; }

        set { _id = value; }

    }

   

}

 

ReferĂȘncia: 1.6

 

         Note que declarei as variĂĄveis, uma do tipo int e outra do tipo string. Para gerar o Get e Set automĂĄtico, utilize o atalho CRTL + R e CRTL + E posicionado o mouse em cima da variĂĄvel. Caso contrĂĄrio utilize o menu refactory / encapsulate field...

 

 

ReferĂȘncia: 1.7

 

         A referĂȘncia 1.7 mostra o local correto onde ficou a classe criada apenas com o Get e Set dos campos. Depois de montado e configurado corretamente, criei a pĂĄgina “Default.aspx” para mostrar os resultados.

 

         Aviso antes que nĂŁo utilizarei o padrĂŁo MVC porque iria aumentar muito este artigo falando apenas de MVC, cujo nĂŁo Ă© o nosso objetivo, mas sim mostrar como funciona o novo sistema utilizando cache e sqldependency.

 

         Dentro da pĂĄgina “Default.aspx”, adicionei o componente GridView com dois campos BoundField. Estes dois campos foram declarados com o mesmo nome da classe “CustomerDetails.cs”. ReferĂȘncia 1.8

 

 

 

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" 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 runat="server">

    <title>CACHE</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">

            <Columns>

                <asp:BoundField DataField="id" />

                <asp:BoundField DataField="customerName" />

            </Columns>

        </asp:GridView>

    </div>

    </form>

</body>

</html>

 

ReferĂȘncia: 1.8

 

 

         Dentro da classe “Default.aspx.cs” Ă© onde estĂĄ o segredo para o cache. No Page_Load preencho o componente GridView chamando um mĂ©todo. ReferĂȘncia 1.9.

 

 

 

protected void Page_Load(object sender, EventArgs e)

    {

        this.GridView1.DataSource = GetDados();

        this.GridView1.DataBind();

    }

 

ReferĂȘncia: 1.9

 

 

         GetDados() Ă© um mĂ©todo que retorna um List<CustomerDetails> utilizando genĂ©rics. Antes de criar o mĂ©todo, importe as seguintes classes. ReferĂȘncia 1.10.

 

 

 

//importes

using System.Web.Caching;

using System.Data.SqlClient;

using System.Collections.Generic;

 

ReferĂȘncia: 1.10

 

 

         O mĂ©todo GetDados nĂŁo recebe parĂąmetros porĂ©m retorna uma lista de dados. Utilizarei SqlDataReader para buscar os dados e preencher a lista.

 

 

 

private List<CustomerDetails> GetDados()

    {

        List<CustomerDetails> customers = null;

        if (Cache["Customers"] != null)

        {

            customers = (List<CustomerDetails>)Cache["Customers"];

        }

        else

        {

            using (SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString))

            {

                try

                {

                    SqlCommand cmd = new SqlCommand("Select id, CustomerName from Customers", cn);

                    cn.Open();

                    List<CustomerDetails> list = new List<CustomerDetails>();

                    customers = FillDados(cmd, list);

 

                    System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString);

                    SqlCacheDependencyAdmin.EnableTableForNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString, "Customers");

                    SqlCacheDependency dep = new SqlCacheDependency("siteDB", "Customers");

                    Cache.Insert("Customers", customers, dep);

                }

                catch (DatabaseNotEnabledForNotificationException ex)

                {

                    throw ex;

                }

            }

        }

        return customers;

    }

 

ReferĂȘncia: 1.11

 

 

Explicação:

 

         Antes de tudo, a anĂĄlise da assinatura do mĂ©todo Ă© muito importante para o resto do entendimento. ReferĂȘncia 1.12.

 

 

private List<CustomerDetails> GetDados()

 

ReferĂȘncia: 1.12

 

É do tipo privado, nĂŁo recebe dados e retorna um List<CustomerDetails> cujo Ă© a classe criada anteriormente.

 

 

        List<CustomerDetails> customers = null;

        if (Cache["Customers"] != null)

        {

            customers = (List<CustomerDetails>)Cache["Customers"];

        }

ReferĂȘncia: 1.13

        

O prĂłximo passo foi declarar uma lista chamada customers igualando ao valor null. Em seguida adicionei uma condição perguntando se o “Cache[“Customers”]” Ă© diferente de null, caso for, a lista “customers” declarada acima receber um cache de dados do Cache[“Customers”].

 

         Caso nĂŁo tiver preenchido serĂĄ necessĂĄrio ir ao banco de dados utilizando a string de conexĂŁo do web.config, fazer um select, buscar os dados e preencher a lista de dados. ReferĂȘncia 1.14

 

 

 

else

        {

            using (SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString))

            {

                try

                {

                    SqlCommand cmd = new SqlCommand("Select id, CustomerName from Customers", cn);

                    cn.Open();

                    List<CustomerDetails> list = new List<CustomerDetails>();

                    customers = FillDados(cmd, list);

 

                    System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString);

                    SqlCacheDependencyAdmin.EnableTableForNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString, "Customers");

                    SqlCacheDependency dep = new SqlCacheDependency("siteDB", "Customers");

                    Cache.Insert("Customers", customers, dep);

                }

                catch (DatabaseNotEnabledForNotificationException ex)

                {

                    throw ex;

                }

            }

        }

 

ReferĂȘncia: 1.14

 

No else, a primeira linha Ă© buscar a conection string. ReferĂȘncia 1.15

 

 

using (SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString))

 

ReferĂȘncia: 1.15

 

 

         Lembre-se que dentro do web.config existe o nome [SiteDB] cujo Ă© a conectionstring adicionada logo no começo deste artigo. Passando para as prĂłximas linhas do cĂłdigo, adicionei try e catch onde faz select no banco de dados, executa datareader, preenche os dados e faz o cache. ReferĂȘncia 1.16

 

 

 

try

                {

                    SqlCommand cmd = new SqlCommand("Select id, CustomerName from Customers", cn);

                    cn.Open();

                    List<CustomerDetails> list = new List<CustomerDetails>();

                    customers = FillDados(cmd, list);

 

                    System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString);

                    SqlCacheDependencyAdmin.EnableTableForNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString, "Customers");

                    SqlCacheDependency dep = new SqlCacheDependency("siteDB", "Customers");

                    Cache.Insert("Customers", customers, dep);

                }

                catch (DatabaseNotEnabledForNotificationException ex)

                {

                    throw ex;

                }

 

ReferĂȘncia: 1.16

 

 

Explicação:

 

         Logo apĂłs o try adicionei um SqlCommand com um select dos campos, abri o banco de dados com o comando Open() e criei uma nova variĂĄvel list do tipo List<CustomerDetails>. ReferĂȘncia 1.17.

 

 

 

SqlCommand cmd = new SqlCommand("Select id, CustomerName from Customers", cn);

cn.Open();

List<CustomerDetails> list = new List<CustomerDetails>();

 

ReferĂȘncia: 1.17

 

 

         Dentro deste mĂ©todo, acabei acessando outro para buscar e executar o SqlDataReader adicionando na lista todo o resultado. Este mĂ©todo chama “FillDados”.

 

 

customers = FillDados(cmd, list);

 

ReferĂȘncia: 1.18

 

         Note que este novo mĂ©todo recebe como entrada SqlCommand e a lista de dados. A lista customers recebe o resultado do mĂ©todo. Antes de terminar o mĂ©todo “GetDados”, mostrarei o mĂ©todo FillDados. ReferĂȘncia 1.19.

 

 

 

private List<CustomerDetails> FillDados(SqlCommand cmd, List<CustomerDetails> list)

    {

        using (SqlDataReader dataReader = cmd.ExecuteReader())

        {

            while (dataReader.Read())

            {

                CustomerDetails coll = new CustomerDetails();

                coll.Id = (int)dataReader["id"];

                coll.CustomerName=(String)dataReader["CustomerName"];

                list.Add(coll);

            }

            return list;

        }

    }

 

ReferĂȘncia: 1.19

 

Explicação:

 

         Adicionei a variĂĄvel dataReader executando o comando cmd.ExecuteReader(). Enquanto estiver dados crio uma variĂĄvel “coll” do tipo CustomerDetails e atribuo os campos Id igual ao resultado do Reader[“id”]. Da mesma forma faço com o CustomerName; adiciono o dataReader[“CustomerName”] e ao final pego a lista criada e adiciono com o Add(coll) passando a variĂĄvel coll.

 

         Ao final preciso retornar uma lista, esta lista deve ser do tipo List<CustomerDetails> cujo tenho o list. ReferĂȘncia 1.20.

 

 

return list;

 

ReferĂȘncia: 1.20

        

ApĂłs retornar a list do mĂ©todo “FillDados” preciso habilitar o cache pelo sqlCacheDependencyAdmin cujo deixo ativo o banco de dados para cache. Preciso habilitar a tabela do banco de dados utilizando o EnableTableForNotifications. No final insiro o cache utilizando o mĂ©todo Cache.Insert. ReferĂȘncia 1.21

 

 

 

customers = FillDados(cmd, list);

 

//habilita o cache para o banco de dados para o uso do cache

System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString);

 

//habilita a tabela do banco de dados para o uso do cache                    SqlCacheDependencyAdmin.EnableTableForNotifications(System.Configuration.ConfigurationManager.ConnectionStrings["SiteDB"].ConnectionString, "Customers");

 

SqlCacheDependency dep = new SqlCacheDependency("siteDB","Customers");

 

 

//inserir o cache

Cache.Insert("Customers", customers, dep);

 

ReferĂȘncia: 1.21

 

 

Explicação:

 

         Note que a linha que habilita o SqlCacheDependencyAdmin serve para autorizar que determinado banco de dados possa utilizar cache. Tenho que passar como parĂąmetro a conectionString dentro do web.config.

 

 

SqlCacheDependency dep = new SqlCacheDependency("siteDB","Customers");

 

ReferĂȘncia: 1.22

 

         Na referĂȘncia 1.22 Ă© onde indico o nome da tag informada dentro do web.config e o nome da tabela cujo desejo fazer o cache. Logo apĂłs basta utilizar o cache.Insert passando a variĂĄvel criada do tipo SqlCacheDependecy.

 

 

 

Cache.Insert("Customers", customers, dep);

 

ReferĂȘncia: 1.23

 

         Com este mĂ©todo, coloco a chave como parĂąmetro, a lista de dados e a variĂĄvel cache. Vejamos o funcionamento do sistema.

Cliquei F5 para iniciar o sistema.

 

 

ReferĂȘncia: 1.24

 

Pela primeira vez, o cache ainda nĂŁo foi feito, portanto o mesmo utiliza o select com todo o procedimento. Coloquei um breakpoint junto ao mĂ©todo PAGE_LOAD. ReferĂȘncia 1.25.

 

 

 

ReferĂȘncia: 1.25

 

 

Apertei F5 no browser e notei que não passou nem mesmo pelo breakpoint que coloquei, ou seja, foi criado um cache cujo nem mesmo precisou acessar o método para retornar os dados.

 

Bom, espero que tenham gostado. Fico por aqui e qualquer problema favor entrar em contato pelo e-mail: mauricio@aspneti.com ou mauricio@ascompras.com.

 

Mauricio Junior

www.aspneti.com

www.mauriciojunior.org