Acesso à Banco de Dados I Conexão

1/9/2008 7:39:00 PM By Felipe Pessoto

Vou dar uma pausa na série Covariância e Contravariância pra falar um pouco sobre conceitos Básicos de Acesso a Banco de Dados.
Tem muita coisa que quero escrever, mas vai depender do meu tempo livre, e ainda tenho que terminar o livro do exame 70-526(já foram 5cap.)
Outro assunto muito interessanta é o LINQ, ele facilita muito o acesso ao banco de dados e dá mais confiança já que é tudo verificado em tempo de compilação. Mas isso fica pra uma próxima oportunidade.

Continuando, vamos estudar um pouco os objetos de conexão.

Primeiro, o que é um objeto de conexão?

O objeto de conexão é um "canal" que seus comandos e querys vão usar para se comunicar ao banco e dados. Ele também vai determinar se você vai usar Pool de Conexões(veremos posteriormente).

O Visual Studio permite que você gerencie suas conexões pela janela Server Explorer. As conexões adicionadas pelo Server Explorer ficam acessíveis à todos os projetos que você criar.
Para adicionar uma nova conexão é muito simples, abaixo mostro como adicionar um arquivo MDB do Access:



Quando você clicar em OK a nova conexão já será adicionada ao Server Explorer.
Pra adicionar uma conexão no SQL Server é só clicar no botão Change e escolher o Microsoft SQL Server. Alguns itens serão adicionados à janela, como a opção se usar autenticação integrada ou um usuário do SQL Server(explicarei adiante).

Outra forma de se criar uma conexão é via código. Nativamente o ADO.Net vem com objetos de conexão para SQL Server(SqlConnection), Oracle(OracleConnection), ODBC(OdbcConnection) e OLE DB(OleDbConnection).
Para usar estes objetos você vai precisar configurar a ConnectionString, indicando o DataSource, Database, Credenciais de Segurança, etc.

Exemplo:

SqlConnection ConnectionSql = new SqlConnection (@"Data Source=.\sqlexpress;Initial Catalog=Northwind;Integrated Security=True");

Neste exemplo conectamos à instância sqlexpress da máquina local, usando o banco de dados Northwind e segurança integrada.

Quando usamos Segurança Integrada, o usuário atual do Windows será usado. Este tipo de autenticação é a mais recomendada, então use-a sempre que possível.

Depois de criada, podemos abrir nossa conexão usando o método Open():

ConnectionSql.Open();

E para fecharmos usamos o método Close():

ConnectionSql.Close();

Sempre que uma conexão muda de estado(como abrir uma conexão fechada), você pode ser notificado usando o evento StateChange:

private void ConnectionSql_StateChange(object sender, StateChangeEventArgs e)
{
Label1.Text = e.CurrentState.ToString();
}

Outro evento interessante é o InfoMessage, ele é disparado quando algum aviso não crítico é recebido do banco de dados.

private void ConnectionSql_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
MessageBox.Show(e.Message);
}

Connection Pools

O Pool de Conexões tem um papel muito importante na questão da performance. Cada vez que é instanciado uma nova conexão é usado muito tempo de processamento, então faz sentido guardarmos as conexões por um tempo antes de destrui-las.
As conexões são reutilizadas quando estão no mesmo processo, application domain e string de conexão.
Podemos controlar o comportamento do Pool de Conexões através da string de conexão, vou listar os valores usados:

Connection Lifetime - Quando uma conexão é devolvida ao pool, é verificado à quantos segundos ela foi criada, se ultrapassar o valor definido aqui, a conexão é destruida.
Load Balance Timeout - O tempo mínimo que uma conexão fica na fila antes de ser destruída.
Max Pool Size - O número máximo de conexões que podem ficar na fila para cada string de conexão.
Min Pool Size - O número mínimo de conexões que devem ficar na fila.

Exemplo:
"Data Source=.\sqlexpress;Initial Catalog=Northwind;Integrated Security=True;Min Pool Size=10"

Caso você queira limpar a fila de uma determinada conexão pode usar o método ClearPool, e também é possível limpar o pool de todas as conexões de um determinado providor usando o método ClearAllPools.

Por padrão o Pool de Conexões já vem ativado, então você não precisa se preocupar em ativa-lo.

Manipulando Erros de Conexão

Para manipular um erro de conexão você usa o try/catch, capturando a exceção SqlException.
Essa classe contém uma coleção SqlErrorCollection na propriedade SqlException.Errors com pelo menos um objeto SqlError.

Exemplo:

try
{
connection.Open();
}
catch (SqlException ex)
{
 
string mensagem = "";
 
foreach (SqlError ConnectionError in ex.Errors)
{
mensagem += ConnectionError.Message + " (error: " + ConnectionError.Number.ToString() + ")" + Environment.NewLine;
 
if (ConnectionError.Number == 18452)
{
MessageBox.Show("Dados de Login Inválidos");
}
}
MessageBox.Show(mensagem);
 
}

Procurando SQL Servers disponíveis na rede

A classe SqlDataSourceEnumerator tem uma propriedade chamada Instance que pode ser usada para buscar por servidor SQL Server na rede. Basta executar o método GetDataSources() e será retornado um DataTable contendo informações sobre cada SQL Server encontrado.
Os servidores encontrados vão depender das configurações da rede, firewall, etc.
O DataTable retornado pelo GetDataSources() conterá as seguintes colunas:

ServerName - Nome do servidor
InstanceName - Nome da instância do SQL Server
IsClustered - Indica se o servidor é parte de um cluster
Version - Versao do SQL Server

Exemplo:

SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance;
MeuGrid.DataSource = instance.GetDataSources();

Aqui acabamos a parte sobre Conexões. Espero escrever a próxima parte em breve.
Até a próxima.

Covariância e Contravariância em C#, Parte Dois: Covariância de Array

1/3/2008 12:52:00 PM By Felipe Pessoto

C# implementa variância de duas maneiras. Hoje apresentarei a maneira incorreta.

Desde o C# 1.0, arrays onde o tipo do elemento é um tipo por referência são covariantes. Isto é perfeitamente correto:

Animal[] animais = new Girafa[10];

Desde que Girafa seja menor que Animal(isto é, Girafa herda de Animal), fazer um array dela é uma operação sobre tipos covariantes. Girafa[] é menor que Animal[], então sua instância se enquadra na variável.

Infelizmente, este tipo particular de covariância não é totalmente correto. Foi acrescentada à CLR porque o Java a implementa e os designers da CLR queriam uma linguagem parecida com o Java. Então foi adicionado ao C#, porque o recurso estava disponível na CLR. Esta decisão foi muito controversa no desenvolvimento, mas não há nada que possamos fazer em relação a isso agora.

Porque está incorreto? Porque deve ser sempre permitido colocar Tartaruga em um array de Animal. Com a covariância da array na linguagem e na runtime você não pode garantir que uma array de Animal pode aceitar uma Tartaruga porque por trás dela pode ser um array de Girafa.

Isto significa que tornamos um erro que podia ser pego pelo compilador em um que só pode ser pego no momento da execução. Isso também significa que toda vez que você colocar um objeto em um array, temos de fazer uma verificação em tempo de execução para garantir que o tipo funciona ou se gera uma exceção. Isso é potencialmente caro se você está colocando muitas coisas no array.

Um exemplo que você pode testar e verificar que realmente passa pelo compilador, mas gera uma exceção em tempo de execução:

class Animal { }
class Girafa : Animal { }
class Tartaruga : Animal { }

Animal[] animais = new Girafa[10];
animais[0] = new Tartaruga();

Na próxima parte vamos discutir uma espécie de variância que foi adicionado ao C# 2.0, que não tem problemas como esse.

Covariância e Contravariância em C#, Parte Um

12/30/2007 11:09:00 PM By Felipe Pessoto

Vou escrever sobre uma série de artigos do Eric Lippert sobre Covariância e Contravariância. Pretendo dividir os artigos em partes como foi feito no original, pra deixar as coisas mais organizadas e fazer mudanças que forem necessárias pra um melhor entendimento.

Nesta primeira parte vamos entender alguns conceitos sobre tipos.

Primeiramente temos que entender que para dois tipos X e Y, pelo menos uma das seguintes afirmações é verdadeira:
X é maior do que Y.
X é menor do que Y.
X é igual a Y.
X não tem nenhuma relação com Y.

Considere uma hierarquia constituída de: Animal, Mamífero, Reptil, Girafa, Tigre, Cobra e Tartaruga, com seus relacionamentos (Mamífero é uma subclasse de Animal, etc). Mamífero é maior do que Girafa, menor que Animal, e, evidentemente, é igual à Mamífero. Mas Mamífero não é nem maior, nem menor, nem igual a Reptil, é apenas diferente.

Imagine que você tenha uma variável, toda variável tem um tipo que lhe é associado. Em runtime você pode armazenar um objeto que é uma instância de um tipo igual ou menor, ou seja, uma variável do tipo Mamífero pode ter uma instância de Girafa armazenados nela, mas não uma Tartaruga.

Esta idéia de armazenamento de um objeto em um local tipado é um exemplo específico de um princípio mais geral chamado de "princípio da substituição". Isto é, em muitos contextos, podemos substituir uma instância de um tipo "menor" por um "maior".

Agora podemos falar de variância. Considere uma "operação", que manipula tipos. Se o resultado da operação aplicada a qualquer X e Y e sempre resulta em dois tipos X' e Y' com o mesmo relacionamento X e Y a operação é considerada covariante. Se a operação inverte a "grandeza" e a "pequeneza" sobre os seus resultados, mas mantém a igualdade e independência, a operação é considerada "contravariante".

Isso é totalmente imaginário e provavelmente não muito claro. Na próxima parte vamos analisar como o C# implementa variância.

LINQ to Object

12/12/2007 12:54:00 PM By Felipe Pessoto

Agora com o Visual Studio 2008 estou fazendo alguns testes com os novos recursos do Framework 3.0 e 3.5.

Vou colocar aqui um exemplo de página que mostra os números pares, usando o LINQ e como fonte de dados um array.

Crie um novo WebSite, sem esquecer de usar o Framework 3.5:

Adicione um Button e um Label:

De dois cliques no Button para gerar o método do evento Click. Dentro do método insira o seguinte código(usei comentários para explicar o código):

 

//Nossa fonte de dados
int[] numeros = { 1, 2, 3, 4, 5, 6 };

//Query do Linq, depois da keyword in, especificamos a fonte de dados
//Usamos where para filtrar os resultados
//retornando só os que tiverem resto da divisão por 2 igual à 0
//o select serve para o Linq saber o que deve retornar
//daqueles que passarem pelo filtro
//no caso o proprio numero, mas poderiamos
//por exemplo retornar num.ToString()
var query = from num in numeros
where num % 2 == 0
select num;

//Passa cada numero retornado pro Label
//Perceba que a variavel query é definida como IEnumerable<int>
//var é um novo recurso do Framework 3.5
//O tipo da variável é definido na compilação
//A variavel continua sendo tipada
foreach (var numero in query)
{
lblResultado.Text += numero.ToString() + "<br>";
}

Agora tecle F5 para abrir o website e clique no Button, vai aparecer os números 2, 4 e 6:

Usando CopySourceAsHtml no Visual Studio 2008

12/10/2007 2:35:00 AM By Felipe Pessoto

Esta ferramente é muito interessante pra quem costuma inserir trechos de códigos no blog ou site.

Infelizmente o instalador dele só está preparado para o VS2005, mas você pode usá-lo no VS2008.

Para isso faça o download desse arquivo zip.

Extraia os 3 arquivos na pasta C:\Documents and Settings\<USUARIO>\Meus documentos\Visual Studio 2008\Addins
Talvez a pasta Addins não exista, então você deve cria-la.

Depois de extraidos ele já está pronto pra usar. Só para confirmar, clique em Tools -> Add-in Manager e verifique se o CopySourceAsHtml está marcado.

Agora é só selecionar o trecho desejado e clicar em Copy As Html...

E o resultado é muito bom:

 

 


   19 NumberFormatInfo NumberInfo = new NumberFormatInfo();


   20 NumberInfo.CurrencySymbol = "@";


   21 NumberInfo.CurrencyDecimalDigits = 4;


   22 DemoBuilder.NumberFormat = NumberInfo;

 

Aqui no blog não vai sair muito bem por causa do pequeno espaço horizontal, mas o html gerado fica com o visual perfeitamente igual Visual Studio.