🔥 Apps, books, system as a service, podcast and more



Nova forma de utilizar cache utilizando Visual Studio.NET 2005

 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

 

Sign up to our newsletter

Receive our latest updates about programming languages, software, database, books, ebooks, classes, jobs and more.

Top