Oi pessoal, conforme dito no post anterior, hoje é meu último dia na Microsoft. Espero que vocês tenham gostado do conteúdo que foi disponibilizado aqui e que o meu próximo blog também atenda a expectativa de vocês.
Já estou com o domínio devidamente registrado, mas ainda estou criando o conteúdo que será publicado na semana que vêm. Com relação ao blog, estou decidindo qual ferramenta vou utilizar (estou analisando o WordPress e Blogger, sugestões?) e publicarei o endereço no meu site.
Fica aqui meus contatos:
E-mail: luticm79@hotmail.com
Skype: luticm
Twiiter: luticm
URL: http://www.lucianomoreira.com
Até o próximo post…
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Olá queridos leitores deste blog. Esse post é mais um que chega sem aviso prévio e muda um pouco as regras do jogo…
A próxima sexta-feira marca o meu último dia de trabalho na Microsoft Brasil. Depois de mais de três anos trabalhando nessa empresa fantástica, decidi que era hora de seguir algumas de minhas aspirações de carreira e partir para outras frentes de trabalho.
Me desligar da Microsoft não foi uma escolha fácil, muito pelo contrário, a idéia vem me acompanhando durante alguns meses de muita reflexão e análise. A empresa sempre me ofereceu excelentes condições de trabalho, grandes desafios e bons amigos, algo difícil de se encontrar em muitas outras empresas.
Se por um lado fica um grande pesar, por outro fica renovada as ambições e metas deste que vos escreve. Mudanças sempre dão aquele friozinho na barriga, mas pode ser que o resultado seja espetacular.
O que esse post significa para você que está acostumado a gastar alguns minutos do seu dia comigo? Não falarei mais sobre SQL Server? Não continuarei colaborando com a comunidade? Longe disso… Trabalhar com a comunidade, blogar e, claro, brincar com o SQL Server e .NET, está no meu sangue e continuarei a fazer tudo isso, como já fazia antes de entrar na MS. O que irá mudar é meu e-mail e url do blog, mas o Luti continuará sendo o mesmo.
E que diabos eu vou fazer da vida?
Parte da minha agenda estará voltada para um novo projeto, onde trabalharei de perto com a computação na nuvem (o Azure está na lista, claro!) e com a outra parte do meu tempo estarei conduzindo consultorias e treinamentos, focados em SQL Server e .NET. Além disso, continuarei com as colaborações para o MSDN/TechNet, artigos em revistas, reuniões técnicas e o que mais aparecer.
Se você quiser entrar em contato, fique à vontade para utilizar o e-mail: luticm79@hotmail.com. Até sexta-feira eu publico o endereço do meu novo blog e mais informações, pois a saga continua.
Espero que nosso caminhos continuem sempre se cruzando, seja através do meu próximo blog, uma eventual consultoria, treinamento ou evento.
Sentirei saudades deste blog…
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Oi pessoal, amanhã eu estou de volta com mais um webcast, onde vou tentar tirar algumas dúvidas com relação ao SQL Server, suas edições e cenários de aplicação. Minha proposta é discutir como podemos usar os diversos recursos do SQL Server de acordo com tipos específicos de aplicações, minimizando o custo para você e sua empresa.
Após a primeira parte teórica, vamos abrir a sessão para um painel de perguntas e respostas, onde quero ouvir de vocês dúvidas sobre como montar/planejar sua aplicação, questionamentos sobre o SQL Server e como podemos tirar o máximo do produto.
Gostou da idéia? Ficou com vontade de discutir sobre o assunto?
Então tire alguns minutos do seu dia e participe!
MSDN Webcast: Saiba qual edição do SQL Server escolher para cada cenário de aplicação
URL: https://www112.livemeeting.com/cc/_XML/microsoft/join?id=S2P4BM&role=attend
Neste Webcast, serão apresentado diversos cenários comuns de aplicações e analisado qual edição do SQL Server melhor se encaixa no seu projeto e bolso. Após a primeira parte, será aberto um painel para debate sobre o assunto em questão.
Início: 18/3/2009 12:00:00 (Brasília)
Duração: 60 minutos
- Luciano Moreira
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Ontem foi anunciado que o CTP1 do ADO.NET Data Services v1.5 (antes conhecido como Astoria) está a caminho! Isso é uma uma ótima notícia, pois muito se tem falado sobre soluções com arquitetura REST, onde o ADO.NET Data Services se encaixa como uma luva, expondo serviços de dados que podem ser consumidos facilmente por diversos clientes, escrito por exemplo, em WPF ou Silverlight.
Também temos discutido isto recentemente dentro da Microsoft, sendo uma abordagem interessante para desenvolvimento rápido de soluções leves, onde não precisamos de todos os recursos (e alguns overheads) trazidos pelo SOAP.
Para entender melhor sobre o assunto, recomendo:
- Anúncio oficial: http://blogs.msdn.com/astoriateam/archive/2009/03/01/announcing-ado-net-data-services-v1-5-ctp1.aspx
- Post do Otavio sobre RESTFul: http://blogs.msdn.com/otavio/archive/2009/02/24/restful-or-not-restful.aspx
- Dev center do ADO.NET Data Services: http://msdn.microsoft.com/pt-br/data/bb931106(en-us).aspx
- Webcasts:
ADO.NET Data Services (Astoria) - http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=pt-BR&EventID=1032382239&CountryCode=BR
Integrando ASP.NET Ajax com o ADO.NET Data Services - https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=pt-BR&EventID=1032403816&CountryCode=BR
Agora vamos torcer para que o CTP1 fique disponível logo!
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Vamos brincar um pouco com o Azure?
Depois que você instala o SDK do Azure (http://www.microsoft.com/downloads/details.aspx?FamilyID=80e3eabf-0507-4560-aeb6-d31e9a70a0a6&displaylang=en) pode disparar o processo do Development Storage, responsável por simular os diferentes modelos de armazenamento existentes na fundação do Azure (blobs, queues e tables). Mas se você não leu a documentação antes de disparar o processo, pode ser que você veja o seguinte erro:
Explico: por padrão o processo do Development Storage vai tentar criar o banco de dados com a estrutura necessária para fazer os três tipos de armazenamento em uma instância nomeada do SQL Server Express, a “localhost\SQLExpress”.
Mas e se você não possui essa instância do SQL Server Express configurada ou quer usar uma outra instância já instalada, seja ela express ou não? A documentação oficial não nos entrega nenhum “how-to”, então resolvi fazer alguns testes e descrevo aqui o resultado.
Alterando a configuração do Development Storage
Partindo do pressuposto que a instância do SQL Server (2005 ou 2008) está instalada, primeiramente vamos disparar o “Windows Azure SDK Command Prompt”. Nota: para este e os próximos passos, eu estou executando-os com elevação de privilégio (run as administrator), por falta de pesquisa para definição das permissões necessárias. Sabe quais são? Deixe um comentário…
Através da documentação vejo que existe o comando DSInit (Development Storage Init), que é bem sugestivo, então executo o comando “DSInit /Server: <instância>” no command prompt aberto, onde “<instância>” é o nome da sua instância, ok? Aqui está o resultado:
Nota: O DSInit é chamado automaticamente quando o Development Storage é iniciado, caso não exista um ambiente já configurado, então você não precisaria fazer esse passo manualmente (a documentação até recomenda não fazer), mas eu preferi fazer tudo passo a passo para entender melhor. :-)
É visível na figura acima que o usuário responsável por executar o DSInit precisa ter acesso ao SQL Server e as permissões necessárias para criar um banco de dados. Usando o Management Studio é possível ver a estrutura criada (abaixo).
Uma vez criado o banco de dados DevelopmentStorageDb eu inicializei o processo do DevStorage e recebi o mesmo erro da primeira figura, indicando que não existe o banco de dados “.\SQLExpress”, então ainda é preciso configurar mais alguma coisa.
Navegue até o diretório bin no caminho de instalação do SDK (“C:\Program Files\Windows Azure SDK\v1.0\bin”, por padrão) e faça uma cópia de segurança do arquivo “DevelopmentStorage.exe.config”. Depois abra o arquivo para editá-lo, configurando o servidor a ser utilizado. Nota: por restrições de segurança, talvez seja melhor copiá-lo para outro local, alterá-lo e depois substituir o arquivo original.
Eu editei o arquivo nos dois lugares marcados em amarelo, substituindo-os pelo nome da instância utilizada. Fiz isso porque além do development storage eu também quero colocar os bancos/tabelas criadas no mesmo servidor SQL Server.
Feito isso você pode disparar o processo do Development Storage e notar que ele será executando sem problema, conforme figura abaixo.
Pronto, se você chegou até aqui está com o Development Storage apontando para a instância do SQL Server que você escolheu!
Configurando os exemplos
Junto com o SDK do Azure também estão disponíveis uma série de exemplos para você se divertir, sendo necessário usar o “rundevstore.cmd” para fazer o build dos projetos e configurar o development storage com a estrutura das tabelas utilizadas por um dos exemplos.
Quando executei o cmd diretamente, o processo estava indo bem até aparecer um problema relacionado com o acesso ao SQL Server. Dei uma olhada nos arquivos existentes e editei o arquivo “MSBuild\Microsoft.Samples.ServiceHosting.targets”, adicionando o “/Server:<instância>” no local marcado em amarelo (abaixo).

Depois disso o processo de montagem dos exemplos foi executado com sucesso.
Que venha toda a plataforma Azure…
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Oi pessoal, como foi o carnaval? Espero que todos tenham descansado e se divertido.
Para essa quarta-feira de cinzas eu trago um post rápido, para aqueles que estão andando colados nas novidades. Saiu recentemente o CTP (Community Technology Preview) do SQL Server 2008 Service Pack 1. Então para aqueles que ainda trabalham com o famoso “eu somente instalo o produto XYZ depois do SP1”, esse é um forte indicativo de que você já pode se preparar para a atualização do SQL Server 2008, caso você ainda não esteja fazendo isso.
Para mais informações, recomendo este post aqui: http://blogs.msdn.com/sqlreleaseservices/archive/2009/02/23/sql-server-2008-service-pack-1-sp1-ctp.aspx
Enjoy!
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Estou brincando um pouco com o PHP rodando no IIS 7, fazendo tanto acessos ao MySQL como ao SQL Server Express. Então vou aproveitar o gancho e deixar aqui algumas dicas que podem te ajudar a não perder tempo com alguns detalhes de configuração do ambiente.
Depois de configurar no IIS um Handler FastCGI para trabalhar com PHP (http://learn.iis.net/page.aspx/375/setting-up-fastcgi-for-php/), você deve ter feito o teste básico do <?php phpinfo() ?> e salvo o teste.php. Guarde ele…
Feito algumas gracinhas com o PHP, foi hora de acessar o MySQL. Editei o PHP.ini e retirei o comentário da linha “extension=php_mysql.dll” e fui usar a função “mysql_connect”, resultado: “PHP Fatal error: Call to undefined function mssql_connect() in …”. Esse erro foi tranquilo, reiniciei o serviço do IIS e alterei a configuração extension_dir para “.\ext” ao invés de “.\”, pois as dlls estavam nesse diretório. Tudo funcionou corretamente e continuei brincando (nota: depois eu voltei o extension_dir para “.\” e o mysql ainda continuou funcionando, o que indica que isso não trouxe nenhum benefício).
Então chegou a hora de usar o PHP para acessar o SQL Server. Como eu havia visto um php_mssql.dll no “php.ini”, fui direto lá e descomentei o bendito, mas quando fui utilizá-lo continuei recebendo o mesmo erro de função indefinida. Depois de alguns testes, deixei esse camarada de lado e baixei o SQL Server 2005 Driver for PHP Cumulative Update – October 2008 (http://www.microsoft.com/downloads/details.aspx?FamilyId=61BF87E0-D031-466B-B09A-6597C21A2E2A&displaylang=en). Importante: esse driver funciona para SQL Server 2008 também, então não precisa ficar correndo atrás de outro.
Nota: nesse meio tempo, passei a usar uma função do php bem interessante, chamada function_exists, que nos ajuda a descobrir se o módulo foi carregado corretamente.
if (function_exists('<nome da funcao>'))
echo "Função encontrada";
else
echo "Aonde está você???";
die("AAAARRRRGGGHHHH");
Fiz o extract do pacote, copiei o arquivo php_sqlsrv.dll para a pasta “ext” do php e configurei no arquivo php.ini esse novo módulo, adicionado “extension=php_sqlsrv.dll”. Pronto, o módulo passou a ser carregado pelo php, a verificação acima parou de reclamar e o teste.php passou a mostrar o módulo do SQL Server carregado.
Quando fui abrir minha primeira conexão e executar uma consulta, recebi outra mensagem de erro! Que passou a ser “SQLSTATE: IM002 - message: [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified”. O que fazer??? Depois de um pouco de pesquisa, descobri que precisamos instalar o SQL Server 2005 ODBC driver a partir do feature pack do SQL Server 2005, que pode ser conseguido aqui: http://www.microsoft.com/downloads/details.aspx?FamilyID=50B97994-8453-4998-8226-FA42EC403D17&displaylang=en.
Feito tudo isso, eu consegui usar o PHP para fazer consultas no SQL Server Express sem a menor dificuldade, o que foi bem legal.
Espero que esse post o ajude a evitar esses pequenos detalhes de configuração, permitindo-o utilizar o SQL Server com PHP. Mais importante, você pode usar a versão Express do SQL Server, que funciona muito bem para aplicações de menor porte e possui recursos avançados, como manipulação de XML, Full-Text Search, Filestream e reporting, o que o habilita a trabalhar com alguns cenários que são restringidos em diversos outros bancos de dados relacionais.
Aproveitando a deixa, pergunto: Você está usando o SQL Server Express? Qual o tipo de aplicação?
Compartilhe aqui o seu caso para discutirmos com o pessoal.
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Hoje de manhã eu recebi uma pergunta de um amigo que queria saber como corromper um banco de dados, para fazer alguns testes. O mecanismo que ele estava utilizando não era efetivo, então eu mencionei que ele poderia usar um editor hexadecimal para fazer o trabalho, mas como não temos muitas referências em português, resolvi gastar alguns minutinhos para machucar um banco de dados. Vamos?
Criando o banco de dados
Execute o script abaixo para criarmos um coitado que será corrompido…
USE master
go
-- drop database BDProblema
CREATE DATABASE BDProblema
go
USE BDProblema
go
ALTER DATABASE BDProblema
SET PAGE_VERIFY NONE
go
CREATE TABLE Dados (
IdDado INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
Nome VARCHAR(200) NOT NULL)
go
INSERT INTO Dados VALUES ('Luciano Caixeta Moreira')
go
Note que eu configurei o banco de dados para não trabalhar com nenhum modelo de verificação de página, pois quero mostrar para vocês uma edição do arquivo sem recebermos nenhuma mensagem de erro.
Analisando a tabela criada com DBCC PAGE
Agora vamos dar uma olhada na estrutura da página. Primeiro descobrimos onde ela está e depois usando o DBCC PAGE para vermos sua estrutura.
SELECT *
FROM sys.sysindexes as s
where s.id = OBJECT_ID('Dados')
/*
First: 0x900000000100
Arquivo = 1
Página = 144 (0x90)
*/
DBCC TRACEON(3604)
DBCC PAGE (BDProblema, 1, 144, 2)
/*
Vamos guardar o início da página, pois é o que importa!
Memory Dump @0x5C19C000
5C19C000: 01010400 00c00001 00000000 00000800 †.....À..........
5C19C010: 00000000 00000100 1b000000 781f8600 †............x..
5C19C020: 90000000 01000000 14000000 40000000 †............@...
5C19C030: 13000000 00000000 00000000 00000000 †................
5C19C040: 01000000 00000000 00000000 00000000 †................
5C19C050: 00000000 00000000 00000000 00000000 †................
5C19C060: 30000800 01000000 02000001 0026004c †0............&.L
5C19C070: 75636961 6e6f2043 61697865 7461204d †uciano Caixeta M
5C19C080: 6f726569 72610000 21212121 21212121 †oreira..!!!!!!!!
*/
Agora vamos executar uma pequena alteração para identificarmos se o 0x4c em negrito é realmente o “L” do meu nome.
UPDATE Dados
SET Nome = 'Muciano Caixeta Moreira'
DBCC TRACEON(3604)
DBCC PAGE (BDProblema, 1, 144, 2)
/*
5C19C000: 01010400 00c00001 00000000 00000800 †.....À..........
5C19C010: 00000000 00000100 1b000000 781f8600 †............x..
5C19C020: 90000000 01000000 14000000 5b000000 †............[...
5C19C030: 02000000 00000000 00000000 00000000 †................
5C19C040: 01000000 00000000 00000000 00000000 †................
5C19C050: 00000000 00000000 00000000 00000000 †................
5C19C060: 30000800 01000000 02000001 0026004d †0............&.M
5C19C070: 75636961 6e6f2043 61697865 7461204d †uciano Caixeta M
5C19C080: 6f726569 72610000 21212121 21212121 †oreira..!!!!!!!!
*/
Aqui vemos que o caractere na posição 0x5C19C06F alterou de 0x4c (L) para 0x4d (M).
Como estamos na página 144, sabemos que o offset dessa página no arquivo em bytes é: 144 * 8192 = 1179648 (em hexadecimal –> 0x120000). Vamos para o editor hexadecimal?
Editando o arquivo BDProblema.mdf
Pare a instância do SQL Server em questão e utilizando o editor hexadecimal de sua preferência (baixei o Free Hex Editor Neo da HDD Software) abra o arquivo BDProblema.mdf.
Navegue até o offset 120000 e a partir daí vá até a posição 6F e encontre o caractere 4d, alterando-o para 4c.
(Antes)
(Depois)
Agora salve o arquivo, feche o editor, reinicie a instância do SQL Server e execute um SELECT na tabela Dados. Qual será o resultado??? O “Muciano” voltou a ser “Luciano”. Até aqui não vemos nenhum erro, pois o SQL Server não estava com nenhuma verificação específica para o banco de dados, o que está para mudar…
Habilitando o page checksum e corrompendo o banco
Primeiramente, execute o script abaixo:
ALTER DATABASE BDProblema
SET PAGE_VERIFY CHECKSUM
go
UPDATE Dados
SET Nome = 'Muciano Caixeta Moreira'
go
DBCC CHECKDB()
GO
DBCC results for 'Dados'.
There are 1 rows in 1 pages for object "Dados".
CHECKDB found 0 allocation errors and 0 consistency errors in database 'BDProblema'.
Como resultado, teremos um banco de dados com CHECKSUM habilitado e a página com seu checksum calculado, pois foi executado um update na tabela. O CHECKDB vai executar com sucesso e nenhum erro será reportado.
Repita do procedimento listado no tópico “Editando o arquivo BDProblema.mdf”, onde você vai alterar o nome “Muciano” para “Luciano” através do editor hexadecimal. Reinicie o serviço do SQL Server e tente executar a consulta abaixo:
SELECT *
FROM Dados
/*
IdDado Nome
----------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Msg 824, Level 24, State 2, Line 1
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0xd73d977b; actual: 0xd73d97fb). It occurred during a read of page (1:144) in database ID 7 at offset 0x00000000120000 in file 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\BDProblema.mdf'. Additional messages in the SQL Server error log or system event log may provide more detail. This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.
*/
Se tentar executar um CHECKDB, vai ver algo parecido com:
DBCC results for 'Dados'.
Msg 8928, Level 16, State 1, Line 1
Object ID 2105058535, index ID 1, partition ID 72057594038779904, alloc unit ID 72057594039697408 (type In-row data): Page (1:144) could not be processed. See other errors for details.
Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 2105058535, index ID 1, partition ID 72057594038779904, alloc unit ID 72057594039697408 (type In-row data), page (1:144). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed. Values are 12716041 and -4.
There are 0 rows in 0 pages for object "Dados".
CHECKDB found 0 allocation errors and 2 consistency errors in table 'Dados' (object ID 2105058535).
CHECKDB found 0 allocation errors and 2 consistency errors in database 'BDProblema'.
repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (BDProblema).
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Pronto! Você está com o seu banco de dados corrompido.
Como é um problema na página de dados, não podemos fazer um rebuild de um índice (método utilizado quando um índice não-cluster está corrompido) e temos que partir para outros métodos de disaster recovery, como recuperar um backup.
Espero que você tenha gostado e te ajudado a entender como pode simular falhas no seu banco de dados, para testar seu planejamento de disaster recovery, antes que seu ambiente de produção não esteja ok e você não sabia o que fazer. Além disso, claro, veja como é importante manter o checksum habilitado!
Até a próxima!
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Attachment(s): CorromperBD.sql
Hoje conversei com um dos nossos clientes que me perguntou se exisita alguma maneira de executar pacotes DTS no SQL Server 2008 rodando em uma plataforma de 64 bits. Em primeiro lugar, eu nem sabia se existia um problema, pois na minha cabeça bastaria pegar e executar o DTEXEC como um processo em modo 32 bits mesmo.
Mas para garantir que eu não estava falando besteira, pesquisei mais sobre o assunto e achei o que queria na documentação oficial do SQL Server:
- BOL: http://msdn.microsoft.com/en-us/library/bb500440.aspx
O BOL diz claramente que “There is no 64-bit design-time or run-time support for DTS packages. On a 64-bit computer, DTS packages, and Integration Services packages that run DTS packages, can run only in 32-bit mode. To run DTS packages in 32-bit mode, you have to install and use the 32-bit version of the dtexec utility (dtexec.exe). To install the 32-bit version of the dtexec utility, select Client Tools or Business Intelligence Development Studio during setup”.
Porém não temos muito mais informação além disso, o que acaba deixando o profissional sem maior embasamento. Como essa história de 32/64 gera muita confusão, pois quando falamos no BIDS (Business Intelligence Development Studio) ele requer o uso de providers 32-bit em design time e somente em run-time pode usar providers de 64 bits. Então achei melhor continuar procurando mais um pouco e encontrei uma thread na nossa lista interna que apontava para esse blog aqui: http://dougbert.com/blogs/dougbert/archive/2008/06/10/64-bit-considerations-for-sql-server-integration-services-final.aspx.
Conteúdo excelente e leitura obrigatória para quem quer saber maiores detalhes sobre o assunto. Façam bom uso!
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Redes sociais estão mudando a maneira como nos relacionamos e como os negócios são conduzidos. Um dos mecanismos que mais cresce atualmente é o twitter e resolvi experimentar. Então aqui estou eu: http://twitter.com/luticm
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
No ano passado foi discutido a possibilidade de termos um fórum unificado de SQL Server entre o MSDN e TechNet, conforme mencionei neste post aqui: http://blogs.msdn.com/luti/archive/2008/07/08/sql-server-no-msdn-e-technet.aspx, lembram?
Pois é, aquela história se tornou verdade e hoje estamos com os fóruns de SQL Server unificados, como pode ser visto abaixo…
- http://social.msdn.microsoft.com/Forums/pt-BR/category/sqlserver/
- http://social.technet.microsoft.com/Forums/pt-BR/category/sqlserver/
Então se você está navegando pelo TechNet ou MSDN, terá acesso os mesmos fóruns, sem necessidade de sair do seu portal preferido para poder usufruir de boas discussões.
Além de criarmos o espelhamento, também tentamos dividir melhor os temas, assim as pessoas poderão postar a dúvida no fórum correto ao invés de ficar colocando o mesmo post em N fóruns, o que só atrapalha os moderadores e a comunidade. Nos próximos dias vocês ainda verão algumas alterãções, como a criação de dois novos fóruns, um voltado para o SSIS e outro para recursos de alta disponibilidade.
Com essas mudanças eu espero que os fóruns continuem sendo um ponto importante de acesso e pesquisa para todos da comunidade, e não somente para aqueles que estão iniciando na tecnologia, mas também para os profissionais mais experientes.
Eu quero ouvir vocês! Gostaram da nova versão do fórum? O que poderia melhorar?
Já assinei os RSSs dos fóruns e estou esperando as threads quentes! Quem venham excelentes discussões…
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Existe uma grande chance de que você tenha visto recentemente anúncios sobre o guia de arquitetura (www.codeplex.com/AppArch) montado pelo time de Patterns and Practices. Mas normalmente o pessoal vai lá, faz o download e não olha algumas coisas interessantes que são oferecidas, como por exemplo, uma série de vídeos sobre o assunto: http://www.codeplex.com/AppArch/Wiki/View.aspx?title=Video%20Index
Muito bom para um fim de dia corrido, onde você quer ouvir alguma coisa rápida e interessante.
Fica aqui a dica…
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Uma questão que aflige muitos desenvolvedores e DBAs, é reconhecer qual o usuário está executando uma determinada operação no banco de dados, quando se utiliza uma conexão genérica com o SQL Server (integrada ou não). Você também já parou para pensar nesse problema? Como resolveu?
A utilização de uma conexão genérica é muito comum em aplicações ASP.NET ou serviços do Windows que ficam recebendo chamadas e executando procedimentos específicos. O que usualmente fazemos? Configuramos a aplicação para utilizar a identidade do processo em questão para acessar o SQL Server (segurança integrada e uma boa abordagem) ou então o pessoal cria um usuário UsrAplicacao e atribui as permissões adequadas… Tá bom, eu sei que vocês têm aquela(ssssssss) aplicação que usa o SA, mas que tal evitar?
Para evitar esse problema, poderíamos configurar nosso processo para personificar a identidade do usuário que acessa a aplicação, atribuindo as permissões adequadas para cada usuário (ou grupo). Até aqui tudo bem, mas o pessoal acaba não aplicando as permissões corretas ou começam a enfrentar problemas como o double-hop do kerberos ou muitos pools de conexão criados (um por usuário). E por fim, voltam a adotar uma conexão genérica.
Tenho uma conexão genérica, o que eu posso fazer? Normalmente as opções são…
1 – Não implementar nenhuma forma de registro (essa é fácil!)
2 – Utilizar a sua biblioteca de logging e, antes ou depois de cada operação no banco de dados, registrar em uma tabela de log o que foi feito e por quem.
3 – Se você somente utiliza procedimentos armazenados, pode colocar mais um parâmetro em todas as operações e registrar isso em uma tabela de log.
Eu já implementei as três opções em diferentes sistemas que eu trabalhei (sim, as três ;-p), mas sempre encontrei alguma dor de cabeça, pois ficava muito dependente do desenvolvedor ou dava um trabalhão. Então vamos analisar mais uma alternativa que apareceu…
CONTEXT_INFO
Estava preparando um webcast e passei pelo CONTEXT_INFO, de onde tirei a idéia para esse post. O interessante foi que quando pesquisei sobre o assunto, encontrei algumas pessoas que já usavam a abordagem que eu tinha em mente, mas infelizmente não acho que seja algo muito difundido. Veja como funciona e se te agrada…
No SQL Server é possível configurar para uma sessão aberta a informação de contexto, contendo 128 bytes com alguma informação específica. Se você abrir uma conexão com o Management Studio e executar o seguinte script, vai receber NULL como resposta.
SELECT CONTEXT_INFO()
SELECT CAST(CONTEXT_INFO() AS VARCHAR)
Isso mostra que por padrão a informação de contexto para uma sessão vem vazia. Agora, se você executar o script abaixo, o resultado será diferente.
DECLARE @binario BINARY(128)
SET @binario = CAST('Luciano Moreira' AS BINARY(128))
SET CONTEXT_INFO @binario
SELECT CONTEXT_INFO()
SELECT CAST(CONTEXT_INFO() AS VARCHAR)
Aqui veremos que o contexto da sessão atual foi alterado e está registrando o meu nome… hhhuuummmm, sacou né? O interessante é que você não consegue limpar o contexto atual através do SET CONTEXT_INFO NULL, apenas consegue o definir como 0x0, o que é totalmente diferente de NULL (faça o teste e execute novamente os dois selects acima). A única maneira de ter o contexto zerado é abrindo uma nova conexão.
Uma abordagem usando CONTEXT_INFO
Com o que você já sabe até o momento, pode começar a implementar sua solução, que consiste em definir um contexto específico após aberta a conexão com o SQL Server.
Partindo do pressuposto que você configurou sua aplicação ASP.NET com autenticação Windows (<authentication mode="Windows"/>), pode utilizar o WindowsIdentity.GetCurrent().Name para identificar quem é o usuário e, antes de executar o comando SQL, definir o contexto:
string comandoContexto = "DECLARE @binario BINARY(128); ";
comandoContexto += "SET @binario = CAST('" + WindowsIdentity.GetCurrent().Name + "' AS BINARY(128)); ";
comandoContexto += "SET CONTEXT_INFO @binario; ";
SqlConnection conexao = new SqlConnection(strConexao);
SqlCommand comando = new SqlCommand(comandoContexto, conexao);
conexao.Open();
comando.ExecuteNonQuery();
comando.CommandText = "INSERT INTO TESTE VALUES ('ZZZZZZZZZZZZ')";
comando.ExecuteNonQuery();
conexao.Close();
No banco de dados, você poderia utilizar uma trigger para registrar quem está fazendo a operação:
CREATE TRIGGER trgI_Teste
ON Teste
FOR INSERT
AS
BEGIN
DECLARE @Usr VARCHAR(200)
SELECT @Usr = CAST(CONTEXT_INFO() AS VARCHAR)
INSERT INTO Audit VALUES ('Insert na tabela teste', @Usr)
END
É claro que essa abordagem ainda dá muito trabalho, pois você teria que colocar isso em toda chamada que fizesse, mas você pode melhorar isso. Como o seu projeto possui uma camada de persistência com funções auxiliares para gerenciar a conexão/comandos, minha sugestão é que você coloque a definição do contexto em um único lugar, de forma transparente para o programador que já está acostumado a usar sua biblioteca. Por exemplo…
Supondo que em sua empresa o padrão de trabalho seja algo do tipo…
using (SqlConnection conexao = AcessoDados.NovaConexao())
{
…
AcessoDados.ExecutarComando(comando, conexao);
}
Aqui você pode incluir o código que define o contexto da conexão no método NovaConexao, mas temos o problema de deixá-la aberta, ou antes de executar o comando no método ExecutarComando. Dessa forma, supondo que sua aplicação atual não faça nenhum controle do usuário e tenha uma biblioteca de acesso a dados, você poderia incluir de forma transparente a informação de contexto, sem gerar retrabalho de codificação.
Sobre a criação de triggers, sei que isso pode gerar um impacto de desempenho se não for bem utilizada, mas coloca o controle de registrar as ações na mão do DBA, não do desenvolvedor, que normalmente vê essa história de audit somente como um trabalho extra, que vai levar mais tempo para codificar. Já vi projetos onde o logging manual somente funciona no início do projeto e, quando o prazo aperta, ninguém se lembra disso.
Refletindo sobre a solução
Ainda não considero essa abordagem uma solução ideal, mas uma vez o contexto definido de forma transparente (em um lugar centralizado, sem impactar centenas de linhas de código), podemos usar a informação dentro de procedimentos ou triggers, sem necessitar passarmos essa informação através de parâmetros ou outros meios.
Outro ponto bacana é que, sendo um campo binário, eu posso passar qualquer coisa no contexto, seja a identidade de um usuário Windows, a identidade de uma autenticação Forms ou outra coisa qualquer, que pode me trazer uma aplicabilidade interessante no dia-a-dia.
Também gosto dessa abordagem por deixar o controle de logging mais focado nas mãos dos DBAs. Em contrapartida, não vejo necessidade de criarmos triggers em todas as tabelas do banco de dados, mas sim naquelas que são mais sensíveis e precisam de um acompanhamento mais detalhado.
Outro detalhe que precisamos levar em conta é o pool de conexões, já que tenho conexões que ficam abertas e são reutilizadas. Por padrão o ADO.NET executa um Connection Reset que, segundo a documentação, deixa o estado da conexão de acordo com um novo login, mas se você usar uma string de conexão com “Connection Reset = false” imagino que pode encontrar problemas. Obs: nos meus testes eu não consegui reproduzir um cenário aonde uma nova conexão vinha com o contexto preenchido (mesmo com reset = false), mas ainda acredito que eu não testei o bastante. :-)
Change Tracking e o contexto
Essa história toda começou quando eu estava brincando com o Change Tracking (CT) e notei que ao executar a função CHANGETABLE ela retornava uma coluna chamada SYS_CHANGE_CONTEXT, do tipo VARBINARY(128). Sugestivo? MUITO!
Particularmente, eu esperava que ao registrar uma alteração na tabela de change tracking, o SQL Server automaticamente pegasse o contexto. Isso seria muito melhor do que usar triggers ou SPs, pois além de não necessitar codificá-las, o CT “injeta” os comandos que registram as alterações de forma transparente, o que me parece mais eficiente e menos problemático.
PORÉM, não é assim que funciona (que droga!). A documentação mostra que precisamos executar nosso comando de INSERT, DELETE ou UPDATE com a cláusula WITH, conforme exemplo abaixo:
DECLARE @originator_id varbinary(128);
SET @originator_id = CAST('MyApplicationID' AS varbinary(128));
WITH CHANGE_TRACKING_CONTEXT (@originator_id)
UPDATE Employees
SET Salary = 50000
WHERE EmpID = 1
Trabalhando dessa forma eu perco a generalização criada na minha camada de acesso a dados (que automaticamente definia o contexto), além de exigir do desenvolvedor que ele saiba quais são as tabelas com change tracking para adicionar o WITH.
Minha expectativa era de habilitar o tracking do contexto automaticamente e, caso ele seja diferente de NULL, o código injetado pelo CT armazenaria o conteúdo na tabela de controle das alterações. No exemplo do BOL, falou o trecho em negrito…
ALTER DATABASE AdventureWorks
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON, TRACK_CONTEXT = ON)
Conclusão
Acho que o CONTEXT_INFO pode nos ajudar em diversos cenários e, mesmo com alguns ajustes e controles manuais, ainda parece uma alternativa interessante para aplicações que utilizam conexões genéricas.
Ainda pretendo refinar um pouco a aplicabilidade do contexto, ver se existe alguma saída automática com o change tracking, alguns blockers e, quem sabe, até ver como isso ficaria com o LINQtoSQL e Entity Framework.
Gostou? Odiou? Sabe como melhorar? Entre em contato.
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Amanhã teremos um webcast sobre a utilização do SQL Server Express, onde serão abordadas suas capacidades e como podemos criar soluções grátis, de maneira fácil, utilizando o distinto. Particularmente eu acho que esse é um webcast muito interessante, pois muitas pessoas não sabem que podem utilizar ferramentas da Microsoft para desenvolvimento de soluções que não precisam ser pagas.
Lembro-me de um evento muito bom que participei, onde tínhamos um público misto (profissionais e estudantes), e fui questionado se havia possibilidade de se criar uma solução .NET que não fosse paga. Claro que sim! E mais do que isso, ainda existia até o mito de que você precisaria de pagar alguma coisa para distribuir uma aplicação winforms, por exemplo. Veja como são as coisas…
Aqui está o link para inscrição no evento: https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032404575&EventCategory=4&culture=pt-BR&CountryCode=BR
Nos encontramos amanhã no webcast, mas dessa vez vou ficar como moderador, enquanto o Roberto comanda o show!
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================
Attachment(s): PostEmPDF.zip
São tantas tecnologias ao nosso redor que diversas vezes não paramos para explorar em detalhes a riqueza e o potencial de cada uma delas.
Recentemente eu tenho investido um pouquinho do meu tempo e olhado com carinho para OBA, Office Business Applications e gostaria de compartilhar com vocês, partindo do princípio, um pouco do que tenho visto. Pensando nisso, gravei um screencast bbeeeemmmm simples, para aqueles que nunca viram nada sobre o assunto…
Aqui está o vídeo disponível no Soapbox:
Video: OBASC_001
Se preferir, pode fazer download do vídeo disponível no meu skydrive:
http://cid-e145f7753042d628.skydrive.live.com/self.aspx/Public/Screencast/ScreenCast%7C_OBA%7C_001.zip
Simples, mas espero que você goste.
Dica: se você quer ser mais eficiente, faça o download e veja o vídeo em “fast playback”. Eu sempre faço isso, gosto e já testei como ficou com o meu vídeo, que mantém uma boa qualidade.
[]s
Luciano Caixeta Moreira
luciano.moreira@microsoft.com
===============================================
This post is provided "AS IS" and confers no right
===============================================