Lazaro's profileLazaro Fernandes Lima - ...BlogListsNetworkMore ![]() | Help |
Lazaro Fernandes Lima - BlogTornar o simples complicado é fácil, tornar o complicado simples é criatividade, vontade e conhecimento. |
||||||
|
|
January 14 ASP.NET Cache: Utilizando dependênciasCache em aplicações web já se tornou uma necessidade extrema para aplicações que crescem muito com o passar do tempo, sendo quase indispensável para que a aplicação seja escalável e performática. Contudo, a maioria das aplicações não trabalha com cache. Neste post iremos trabalhar com scripts de cacheamento em queries do banco de dados, cache de arquivos (proximos artigos). Podemos trabalhar com cacheamento nativo utilizando DEPENCÊNCIAS desde o ASP.NET 2.0. Irei utilizar um banco de dados próprio, com 10000 registros em uma determinada tabela, SQL Server 2005, Visual Studio 2008 com framework 3.5.
Cache de queries do banco de dados Primeiramente, baixe o banco de dados, no SQL SERVER 2005, attache o mesmo à uma instância ativa do SQL SERVER 2005 para que possamos utilizar a tabela com os 10000 registros. Após configurado o banco de dados vamos a etapa de desenvolvimento da aplicação. Crie um WebSite, com framework 3.5.
Adicione um evento de click ao btnObterDados, o mesmo deve ficar da seguinte maneira: protected void btnObterDados_Click(object sender, EventArgs e) { //O objeto StopWatch será o nosso MEDIDOR, irá contabilizar o O código esta auto-explicativo, baixe o projeto em meu skydrive para verificar uma implementação mais detalhada onde utilizei paginação no gridview. Os resultados obtidos com esta implementação ficam claramente positivos quanto a performance da aplicação. Vale lembra que, é necessário ter o Service Broker habilitado e que quaisquer alterações nos dados da tabela que incluem as colunas exibidas, como alteração de um campo, automaticamente, remove o cache da aplicação. É aqui que mora a vantagem da implementação tradicional. Testem updates no banco. Ate mais Baixe o banco de dados e a aplicação. October 12 Desenvolvendo com LINQBuscando utilizar uma sintaxe de pesquisa que atue sobre uma arquitetura orientada a objetos, o LINQ (Language Integrated Query) possibilita uma navegação mais próxima ao nível da mesma.
Em pesquisas baseadas em listas, estamos acostumados a iterar sobre cada elemento efetuando um foreach ou outro tipo de laço na linguagem utilizada e efetuando as condições para exclusão ou inclusão de registros. Com o LINQ necessitamos de uma lógica totalmente aplicada ao design OO, que busque iterar sobre estes objetos, o que torna nossa implementação organizada e com maior produtividade, baseado em arquiteturas orientadas a objetos.
Gosto de exemplos que busquem sua aplicação no mundo real e que possibilitem uma compreensão ampla do assunto, logo, abaixo estão implementadas três classes para um exemplo relativamente simples, sendo esta uma implementação de controle de usuários e suas permissões no sistema.
/*===================================*/ public class PermissaoTipo private bool status; public class Permissao private bool status; public class Usuario private string nome; private bool status; /*===================================*/ As classes acima contém a estrutura de permissões do nosso modelo de sistema para as pesquisas com LINQ.
Basta adicionar as classes acima e já podemos adicionar várias funções a usuários no sistema. Nosso objetivo é efetuar pesquisas sobre estes usuários da forma tradicional e da forma orientada a arquitetura do LINQ, utilizando diversas sintaxes da mesma.
Antes de iniciarmos nosso modelo de sistema, vejamos abaixo uma pesquisa simples em um array de strings, o exemplo é demonstrado baseado no modo tradicional e outro utilizando LINQ, cada um retorna um IList<T> e IEnumerable<T> genéricos.
/*===================================*/
string[] usuarios = new string[] { "Lazaro", "Zezinho", "Zezinha", "Liminha", "Lulinha" }; //iteração tradicional para obter somente usuários que iniciem com a letra "L" IList<string> _lUsuarios = new List<string>(); //interação utilizando LINQ foreach (string usuario in _lUsuarios) Console.WriteLine(""); foreach (string usuario in _lUsuariosLINQ) /*===================================*/
Primeiramente, estamos utilizando interfaces para listas genéricas para armezenar o resultado da seleção, muitos desenvolvedores perguntam se este var é uma variante, a resposta é, não, é somente um atalho para um IEnumerable<T>.
Segundo, nossa sintaxe LINQ tem basicamente três passos, são eles: from
where select Onde, o objeto criado na cláusula from é uma variável que será tipada em tempo de compilação, sem a necessidade de instanciação da mesma para um tipo definido, este processo se torna transparente, uma vez que o compilador já sabe o que a lista passada irá retornar, este recurso é fantástico. Um dos mais poderosos recursos do framework 3.5 é a possibilidade de se trabalhar com este recurso como demonstrado acima, tornando o design altamente orientado a objetos, evitando Type Cast e possíveis erros de conversão em nossa lógica.
Terceiro, no exemplo com LINQ, estamos evitando a passagem de registro à registro para verificar se o mesmo atende ao critério definido para a pesquisa, acelerando e tornando o processo transparente para o desenvolvedor. Em artigos futuros iremos demonstrar que o LINQ se demonstra muito eficiente no quesito performance.
[Mão na massa] Com base nas classes acima, nosso objetivo agora é cadastrar 4 funções no modelo de sistema.
Ao todo serão 3 passos antes de iniciarmos com as pesquisas, são eles: [definir os tipos de permissao], [definir as permissoes inserindo seus tipos] e [definir os usuário e suas funções] /*===================================*/ IList<PermissaoTipo> olPermissaoTipo = new List<PermissaoTipo>(); oPermissaoTipo = new PermissaoTipo(); oPermissaoTipo = new PermissaoTipo(); #region Definindo as Permissäes e suas caracter¡sticas IList<Permissao> olPermissao = new List<Permissao>(); Permissao oPermissaoTotal = new Permissao(); Permissao oPermissaoParcial = new Permissao(); Permissao oPermissaoMinima = new Permissao(); #region Definindo os usu rio e seus n¡veis de permissÆo IList<Usuario> olUsuario = new List<Usuario>(); Usuario oUsuario1 = new Usuario(); Usuario oUsuario2 = new Usuario(); Usuario oUsuario3 = new Usuario(); Usuario oUsuario4 = new Usuario(); #region Visualizando as permissoes e tipos de permissoes de cada usuario foreach (Usuario usuario in olUsuario) /*===================================*/ O retorno esperado é visualizado abaixo (clique para ampliar): Este tipo de sintaxe permite trabalharmos com métodos anônimos, na verdade, é uma evolução dos métodos anônimos do framework 2.0 e um recurso novo no framework 3.5, iremos futuramente ampliar nossos conhecimento em lambda em artigos futuros. Conclusão Muito da arquitetura do LINQ precisa ser comentada e discutida pela comunidade, em breve novos artigos serão inseridos sobre a arquitetura do LINQ. Espero que tenham gostado deste artigo http://msdn.microsoft.com/pt-br/magazine/cc163400.aspx - A evolução do LINQ e seu impacto no design do C# http://www.linhadecodigo.com.br/Artigo.aspx?id=1622 - Lambda Expressions http://msdn.microsoft.com/en-us/netframework/aa904594.aspx - The LINQ Project http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx - 101 LINQ Samples August 19 RAID - AnáliseOlá pessoal, Lendo um white paper sobre arquitetura de bancos de dados SQL Server da Microsoft obtive diversas respostas para dúvidas quanto as melhores práticas em uma arquitetura utilizando ambientes em RAID (Redundant Array of Independent Disks). Sendo altamente recomendado a sua utilização quando problemas relacionados a disponibilidade de informações e alta taxa de I/O de dados afetam nossos ambientes. Segue abaixo descrição dos níveis 0, 1, 5 e 10 de ambientes RAID aplicados a estratégias de arquitetura de banco de dados. RAID0 (simple striping): Baixo custo, sendo o tipo mais simples de se configurar dentre os apresentados, excelente performance para armazenamento e leitura, uma vez que, vários discos estarão responsáveis pelo I/O, acelerando no minimo 100% sua performance. Seu ponto fraco esta na falta de tolerância à possíveis falhas. RAID1 (simple mirroring): Cria uma cópia exata, espelhada, de todos os dados entre dois ou mais discos. Este nível provê boa redundância, porém, baixa eficiencia em armazenamento, não sendo indicado para performance em I/O e sim, segurança e maior disponibilidade dos dados, uma vez que, todos os dados estarão sendo espelhados em outras unidades de disco automaticamente. RAID5 (striping with parity): Nível mais popular utilizado na indústria (segundo documentos da Microsoft). Indicado para menor Input e maior Output de dados, provê uma distribuição de paridade em discos de forma alternada ao qual estas informações sao utilizadas para montar os dados em caso de perda de algum disco, (numero total de drives – 1) / (numero total de drives), claro, baseado em discos idênticos RAID10 (0+1) (stripe of mirrors): Este aqui é o mais indicado para a maioria dos casos, porém, 4 discos são necessários para a menor implementação deste nível de RAID, seu custo é o mais alto. Combina o melhor do RAID0 e RAID1, boa performance e excelente tolerância à falhas. A eficiência na utilização dos níveis de RAID variam de casos para casos conforme podemos analisar acima. A utilização deste ambiente RAID controlado via hardware é altamente recomendado, uma vez que, o S.O. estará totalmente responsável pelo controle deste ambiente, e sabemos que isto não cheira muito bem ;) Referências: Até mais ;) August 18 Dynamic SQLEu me lembro quando programava com ASP 3 e sempre dava uma olhada em scripts SQL montados diretamente no código fonte. Como abaixo: dim sql objConn.execute(sql) É um perigo esse tipo de codificaçao! Já no SQL SERVER 2005, este tipo de construção de script também está disponível, ele se chamada Dynamic SQL. Ou em casos em que limpe, altere ou exiba uma determinada tabela com determinadas colunas, onde, no SQL SERVER 2000 esta funcionalidade de 'concatenar' um script com tabelas, colunas, instruções e executar a partir de uma variável não esta disponível. DECLARE@COLUMNS AS VARCHAR(200)
A utilização de Stored Procedures SEM Dinamic SQL, ainda é mais rápida "na maioria dos casos", mas podemos utilizar o SP_EXECUTESQL, conforme link de documentação ao final do post, sendo esta Stored Procedure responsável por armazenar em batch o plano de execução da dynamic sql, vale lembrar que, principalmente em queries em que a sua utilização é constante, só utilize dynamic sql quando necessário, uma vez que, os scripts executados em Dynamic SQL não são armazenados em cache, exeto pelo uso da sp_executesql como comentado, quem possuir dados estatísticos por favor comentem ;)
A minha opinião sobre este assunto ainda é imatura pelo fato de não ter utilizado muito esta feature presente desde a versão 2005, mas questões como segurança ( Ataque SQL Injection ) e performance me preocupam bastante. Fora isso, ele pode ser utilizado para melhorar o desempenho em SPs com muitas condicionais com certeza Até mais. ;)
http://msdn.microsoft.com/en-us/library/ms188001(SQL.90).aspx - Referência para a sp_executesql Limpeza de registros otimizadaUma das novidades mais interessantes do SQL SERVER 2005 são as CTE ( Common Table Expressions ) e novas funções de ranking. No SQL SERVER 2000 quando precisávamos de uma tabela temporária local, por exemplo, era necessário construir a tabela com uma estrutura para comportar a inserção e logo após o seu uso era necessário efetuar o comando drop table ou deixar que o SQL SERVER fizesse o servico sozinho. Já com as CTE as coisas são mais rápidas e eficientes, com elas agora e possível inserir, editar e remover registros direto da tabela original por meio da CTE. Vejam abaixo: CREATE TABLE minha_tabela1 insert minha_tabela1 values(1,'abc','1') go GO Vejam a simplicidade do script acima para limpeza de registros duplicados. ROW_NUMBER() retorna um número sequencial (iniciado por 1) representando o número de um determinado registro agrupado pela clausula PARTITION BY, esta clausula faz a divisão dos registros duplicados e retorna a identificação do mesmo no resultado. Esta nao e sua única utilidade, sendo possível tambem, construir queries recursivas. WITH expression_name [ ( column_name [,...n] ) ]
até mais ;) |
Public folders
|
||||
|
|