Problemas de cache no SQL Server

Se você estiver recebendo uma mensagem do tipo:

O SQL Server encontrou %d ocorrência(s) de liberação de armazenamento em cache para o cache '%s' (parte do cache do esquema) devido à manutenção do banco de dados ou operações de reconfiguração.
ou
SQL Server has encountered %d occurrence(s) of cachestore flush for the '%s' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
É porque, segundo a MSDN, ao limpar o cache do plano gera uma recompilação de todos os planos de execução subseqüentes e pode provocar uma queda repentina e temporária no desempenho da consulta. Para cada armazenamento em cache limpo no cache do plano, aparece a mensagem supracitada.

Para resolver isso, basta ir no banco correspondente, clicar com o direito sobre ele e escolher Properties (Propriedades). Entre em Options (Opções) e configure o Auto-Close (Fechamento Automático) para False.

Error 500 Internal Server Error - Como descobrir o problema

Quando dá esse erro muitas pessoas tremem só de ver! Abaixo darei uma dica para quem é marinheiro de primeira viagem e se depara com isso.

Essa tela é gerada pelo IIS para camuflar o erro para o usuário. Se a aplicação não for bem tratada quanto a erros, esse é o último recurso que o IIS faz para não exibir o erro na tela. Seria bem incômodo para o usuário ver na tela o erro de seu site, por exemplo. Para quem está gerenciando a aplicação é incômodo até certa parte, pois muitas vezes o desenvolvedor resolve o problema mais olhando o erro do que analisando log, events, etc. Pois bem, vamos lá!

Abra o IIS e procure pela função Error Pages (Páginas de Erro) no módulo IIS. Entre e procure pelo link Edit Resource  Settings (Editar Configurações de Recurso). Ao abrir, a tela de Edit Error Pages Settings (Editar Configurações de Página de Erro) escolha a opção Detailed errors (Erros detalhados) e OK.


Ou, mais especificamente para o ASP.NET, procure a função .NET Error Pages (Páginas de Erro do .NET) no módulo ASP.NET. Entre e procure pelo link Edit Resource  Settings (Editar Configurações de Recurso). Ao abrir, a tela de Edit Error Pages Settings (Editar Configurações de Página de Erro) escolha a opção Desactive (Desativar) e OK.


Com isso, a depender do erro, já estarão sendo enviados para a tela. Lembram do post sobre segurança? No web.config, deixe o customErrors com o atributo mode="Off" caso necessário para que os erros sejam exibidos.

Caso ainda não tenha descoberto o problema, acesse a configuração do ASP  no módulo IIS. Expanda a propriedade Debugging Properties (Propriedades de Depuração) e coloque como True a função Send Errors to Browser (Enviar Erros ao Navegador).


Isso deve ser mais do que o suficiente para exibir o erro e identificar qual o problema está na aplicação. Lembrando que, se preferível, não deixar o erro ser exibido para o cliente. Deve-se fazer o possível para tratar e localizar adequadamente o problema. Segurança em primeiro lugar!

Cufon na Master Page

Para quem está com problemas no carregamento/aplicação do Cufon quando estiver usando Master Page, chame-o da seguinte forma:

<script>
Cufon.now();
function pageLoad(sender, args) {
      Cufon.refresh();
}
</script>

Assim ele aplica corretamente após o carregamento da página.

Out of Memory at Line - Memória Insuficiente

Dica rápida para quem tiver esse tipo de problema: remova o atributo LoadScriptsBeforeUI='false' from ScriptManager. Dentro de Grid editáveis ou em formulários dinâmicos a validação do Javascript falha quando estiver fazendo esse tipo de otimização.

Integração ASP.NET (C#) com o Google Analytics

Nesse artigo irei demonstrar como fazer consultas no Google Analytics, de um determinado site, para ser usado em cálculos estatísticos afim de gerar gráficos semelhantes. Ou seja, irei demonstrar como fazer a consulta e retornar os dados. Os gráficos e exposição dos dados ficará ao seu critério. Ao final poderá ter algo assim:


Primeiramente e óbvio, é preciso dos dados da conta Google como o e-mail e senha para autenticação. Cada site cadastrado no Analytics tem um ID do Perfil e ele pode ser localizado na seguinte página  de Configurações do Perfil. Através desse Id é que consultamos os dados de um determinado site.


Com esses dados em mãos, vamos ao entendimento da integração. O Google disponibilizou um framework que auxilia na consulta e retorno de dados em .NET e ela pode ser baixada no Google GData. Dentro dela contêm vários binários mas precisaremos apenas dos seguintes:

  1. Google.GData.Analytics.dll
  2. Google.GData.Client.dll
  3. Google.GData.Extensions.dll

Adicione-os ao seu projeto. Mas antes de começar a programar isso, vamos ao entendimento das consultas realizadas. No link http://code.google.com/intl/pt-BR/apis/analytics/docs/gdata/gdataExplorer.html tem um simulador que será similar à consulta feita pela sua aplicação. Já no link http://code.google.com/intl/pt-BR/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html contêm toda as especificações necessárias.
Como não gosto de perder tempo e, para muitos pode ser um pouco confuso o seu entendimento logo de cara, vamos fazer uma abstração:

  • ids: é o ID do Perfil conforme vimos anteriormente;
  • dimensions: vamos "acatar" que seja os relacionamentos (linhas)  (não é obrigatório);
  • metrics: vamos "acatar" que seja o que deseja buscar (colunas);
  • segment: especificação do tipo de consulta (não é obrigatório); 
  • filters: é o WHERE da consulta (não é obrigatório);
  • sort: ordenação  (não é obrigatório);
  • start-date: data de início (formato yyyy-MM-dd);
  • end-date: data final (formato yyyy-MM-dd);
  • start-index: serve para paginar dados (como o MySQL usa o LIMIT);
  • max-result: quantidade máxima de registros retornados.

Essa é a explicação mais entendível possível e que posso passar para vocês. Logo, antes de botar a mão na massa, sugiro fazer várias simulações e ver como é retornado os objetos. De acordo com a simulação que fiz, por exemplo, e de acordo com a figura seria a seguinte busca:

"Me retorne todas as cidades, que visitaram meu blog, com suas respectivas quantidades de visitas no período de 03/07/2011 a 17/07/2011 ordenada por cidade. Só me traga os 50 primeiros registros."

Então, me seria retornado a seguinte "tabela":


Ficou claro? Tranquilo, né? A pior parte já passou. Agora, porquê escrevi "tabela"... Porque não é! Lembra que abstraímos para que seja isso. Sabendo de como a API trabalha então bastemos implementar. Vamos lá! Pode-se criar uma classe ou incorporar na mesma página o código. Fica a seu critério!

Adicione os seguintes namespaces:

using Google.Analytics;
using Google.GData.Analytics;
using Google.GData.Client;
using Google.GData.Extensions;

Também as variáveis abaixo são necessárias para a devida autenticação e consulta nas quais descrevem:

// Variáveis
string user; // Usuário da Conta Google Analytics
string pass; // Senha  da Conta Google Analytics
string id_tabela; // ID do Perfil

// Inicialização
user = "email@gmail.com";
pass = "senha";
id_tabela = "ga:30897221"; // Tem que colocar a string "ga" na frete do ID do Perfil

Agora adicione os seguinte métodos:

/// <summary>
/// Consulta o Analytics
/// </summary>
/// <param name="query"></param>
    private DataFeed ConsultaAnalytics(DataQuery query)
    {
        AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0");
        asv.setUserCredentials(user, pass);
        String baseUrl = "https://www.google.com/analytics/feeds/data";
        query.Ids = id_tabela;
        query.Uri = new Uri(baseUrl);
        return asv.Query(query);
    }


/// <summary>
/// Retorna o resultado da consulta
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
    private DataTable RetornaTabela(DataQuery query)
    {
        DataTable resultado = new DataTable();
        DataFeed feed = ConsultaAnalytics(query);
        if (feed.Entries.Count > 0)
        {
            // Cria as colunas
            DataEntry colunEntry = feed.Entries[0] as DataEntry;
            foreach (Dimension colundimension in colunEntry.Dimensions)
                resultado.Columns.Add(new DataColumn(colundimension.Name.Substring(3)));
            foreach (Metric colunmetric in colunEntry.Metrics)
                resultado.Columns.Add(new DataColumn(colunmetric.Name.Substring(3)));          


            // Insere os dados
            foreach (DataEntry singleEntry in feed.Entries)
            {
                DataRow rw = resultado.NewRow();
                foreach (Metric metric in singleEntry.Metrics)
                    rw[metric.Name.Substring(3)] = metric.Value;
                foreach (Dimension dimension in singleEntry.Dimensions)
                    rw[dimension.Name.Substring(3)] = dimension.Value;
                resultado.Rows.Add(rw);
            }
        }
        return resultado;
    }

Óbvio que essas são apenas sugestões de implementações e você podem mudar o quanto achar melhor a depender de sua unidade de negócio. Agora vamos fazer aquela consulta:


        // Dados da consulta
        DataQuery q = new DataQuery();
        q.Dimensions = "ga:city";
        q.Metrics = "ga:visits";
        q.GAStartDate = DateTime.Parse("03/07/2011").ToString("yyyy-MM-dd");
        q.GAEndDate = DateTime.Parse("17/07/2011").ToString("yyyy-MM-dd");
        q.Sort = "ga:city";
        q.NumberToRetrieve = 50;


        // Resultado
        DataTable resultado = RetornaTabela(q);


Pronto! Irá me retornar um DataTable com aquela tabela de dados. Basicamente todas aquelas informações que você vê no Analytics são vindas em formato tabela e que, posteriormente, são feitos tratamentos e cálculos sobre eles. Como disse no início do artigo, agora basta usar a tabela de dados conforme desejar...
Espero que tenham gostado depois de um tempo sem postar nada...