LINQ to SQL - Criando e usando um DataContext
Pode parecer estranho eu estar tocando no assunto LINQ to SQL , quando ainda não se tem uma posição oficial sobre a sua continuidade. Pessoalmente eu creio que mesmo que for descontinuado ainda haverá uma tempo onde a compatibilidade com outro recurso, provavelmente o Entity Framework, será mantida.
De qualquer forma os conceitos abordados referem-se ao LINQ e não serão totalmente descartados. Vou falar sobre o DataContext e neste sentido você pode fazer um paralelo com o Context do Entity Framework.
Um Data Context é um objeto do tipo System.Data.Linq.DataContext que suporta a atualização e manutenção de um banco de dados para objetos conhecidos do LINQ efetuando o tratamento da conexão do banco de dados, dessa forma ,para acessar as tabelas de um banco de dados elas devem estar mapeadas e disponíveis em um objeto Data Context.
Vamos trabalhar neste artigo usando como um banco de dados hipotético chamado Exemplo.mdf e duas tabelas Exemplo e Salario.
A estrutura do banco de dados e do arquivo Data Context é mostrado a seguir:
Para gerar o Data Context usando o assistente clique com o botão direito do mouse sobre o nome do projeto e selecione Add New Item;
A seguir selecione o Template LINQ to SQL Classes e informe onome ExemploDataContext.dbml e clique no botão Adicionar;
A seguir a partir da janela DataBase Explorer selecione as duas tabelas do banco de dados Exemplo.mdf e arraste para o descritor LINQ to SQL;
Pronto com isso temos o DataContext - ExemploDataContext - criado e pronto para usar nos exemplos a seguir.
Você pode tornar as tabelas de um banco de dados que deseja acessar disponíveis de duas formas:
DataContext ExemploDataContext = new DataContext(connString); Table<Exemplo> Exemplo = ExemploDataContext.GetTable<Exemplo>();
No código acima criamos um Data Context chamado ExemploDataContext e uma coleção Table: Exemplo (para uma tabela Exemplo de um banco de dados), disponível naquel contexto.
Uma nova classe coleção
generic, Table<T> , existente no namespace
System.Data.Linq
é usada para
representar as tabelas de um banco de dados. Ela implementa as
interfaces IEnumerable<T> e IQueryable<T>
e ITable que por sua vez implementa IEnumerable
and IQueryable.
Usamos também o método GetTable<T> do Data Context para criar um objeto Exemplo do tipo Table<Exemplo> no contexto ExemploDataContext.
O argumento do construtor DataContext é a string de conexão, a mesma que você com ADO .NET. Abaixo temos um exemplo de uma string e conexão para acessar um banco de dados chamado Exemplo:
String connString = @" Data Source=.;Initial Catalog=Exemplo;Integrated Security=True";
Como resultado temos que o nosso banco de dados passa a ser conhecido para o LINQ como ExemploDataContext e a tabela Exemplo passa a ser conhecida como o objeto Exemplo.
Uma forma mais elegante e recomenda de usar o Data Context é usar um Data Context fortemente tipado conforme o exemplo abaixo:
public partial class ExemploDataContext : DataContext { public Table<Exemplo> Exemplo; public ExemploDataContext(String connString) : base(connString) {} }
- Neste exemplo eu declarei a classe ExemploDataConext que representa um Data Context que possui um campo , Exemplo , para o a tabela Exemplo do banco de dados;
- O construtor chama o construtor base DataContext com a string de conexão;
- Para usar
o contexto fortemente tipado, foi criada uma instância do mesmo
realizando um consulta como :
ExemploDataContext exemplo = new
ExemploDataContext(connString);
-Neste caso nosso banco de dados é visto pelo LINQ como objeto exemplo e a tabela Exemplo conhecida como Exemplo;
- A partir dai podemos codificar os objetos LINQ para fazer tudo oque precisamos para o LINQ gerenciar a tabela Exemplo do banco de dados como uma coleção Exemplo.
A seguir temos um exemplo onde estamos efetuando a consulta a tabela Exemplo do banco de dados Exemplo.mdf usando os objetos LINQ em memória. Note que para isso precisamos primeiro instanciar um objeto DataContext:
using System; using System.Linq; namespace LINQ_DataContext { class Program { public static void Main(string[] args) { Console.WriteLine("Efetuando uma consulta LINQ"); ExemploDataContext exemplo = new ExemploDataContext(); var consulta = from p in exemplo.Exemplo from s in exemplo.Salario where p.ID == s.ID select new { p.Nome,s.Salario }; foreach(var linha in consulta) { Console.WriteLine("Nome : {0} ", linha.Nome ); Console.WriteLine("Salario: {0} ", linha.Salario); } Console.Write("Pressione algo para continuar . . . "); Console.ReadKey(true); } } } |
Neste exemplo estamos consultando os dados de duas tabelas : Exemplo e Salario usando o Data Context como um canal pelo qual efetuamos uma consulta LINQ para consultar o banco de dados e o resultado é retornado em objetos na memória.
Por trás dos panos a classe DataContext transforma a consulta LINQ em uma consulta SQL para visualizar a consulta SQL enviada ao banco de dados podemos usar a propriedade Log da classe Data Context :
Veja abaixo o mesmo exemplo usando a propriedade Log que redireciona o log para o console:
using System; using System.Linq; namespace LINQ_DataContext { class Program { public static void Main(string[] args) { Console.WriteLine("Efetuando uma consulta LINQ"); ExemploDataContext exemplo = new ExemploDataContext(); exemplo.Log = Console.Out; var consulta = from p in exemplo.Exemplo from s in exemplo.Salario where p.ID == s.ID select new { p.Nome, s.Salario }; foreach(var linha in consulta) { Console.WriteLine("Nome : {0} ", linha.Nome ); Console.WriteLine("Salario: {0} ", linha.Salario); } Console.Write("Pressione algo para continuar . . . "); Console.ReadKey(true); } } } |
Existe uma outra maneira de verificar a consulta SQL enviada pelo LINQ que é através do método GetCommand do DataContext que permite visualizar as instruções SELECT.
Este método requer a consulta LINQ como um argumento e retorna um objeto da classe DBCommand e você pode usar a sua propriedade CommandText para retornar o comando SQL usado pelo LINQ to SQL para retornar os registros do banco de dados.
Por outro lado o método GetChangeSet é usado para as instruções INSERT, UPDATE E DELETE, ele retorna um objeto da classe ChangeSet que contém as propriedades Inserts, Updates e Deletes. Elas dão acesso a uma lista de objetos que é alterada depois que um objeto associado a tabela do banco de dados é modificada.
Veja a seguir a utilização destes comandos no mesmo exemplo assim:
using System; using System.Linq; namespace LINQ_DataContext { class Program { public static void Main(string[] args) { Console.WriteLine("Efetuando uma consulta LINQ"); ExemploDataContext exemplo = new ExemploDataContext(); var consulta = from p in exemplo.Exemplo from s in exemplo.Salario where p.ID == s.ID select new { p.Nome, s.Salario }; Console.WriteLine(exemplo.GetCommand(query).CommandText); Console.WriteLine(); foreach(var linha in consulta) { Console.WriteLine("Nome : {0} ", linha.Nome ); Console.WriteLine("Salario: {0} ", linha.Salario); } Exemplo exemplo = new Exemplo(); exemplo.ID = 10; exemplo.Nome = "Macoratti"; exemplo.Exemplo. InsertOnSubmit (exemplo); Console.WriteLine(); Console.WriteLine(exemplo.GetChangeSet().ToString()); Console.Write("Pressione algo para continuar . . . "); Console.ReadKey(true); } } } |
Neste exemplo temos que o objeto ChangeSet contém um objeto inserido; através da propriedade Inserts você pode acessar o novo objeto Exemplo incluído a coleção Exemplo através do método InsertOnSubmit.
Lembre-se que até o momento o banco de dados não foi sensibilizado para isso devemos usar o método SubmitChanges conforme abaixo:
using System; using System.Linq; namespace LINQ_DataContext { class Program { public static void Main(string[] args) { Console.WriteLine("Efetuando uma consulta LINQ"); ExemploDataContext exemplo = new ExemploDataContext(); var consulta = from p in exemplo.Exemplo from s in exemplo.Salario where p.ID == s.ID select new { p.Nome, s.Salario }; Console.WriteLine(exemplo.GetCommand(query).CommandText); Console.WriteLine(); foreach(var linha in consulta) { Console.WriteLine("Nome : {0} ", linha.Nome ); Console.WriteLine("Salario: {0} ", linha.Salario); } Exemplo exemplo = new Exemplo(); exemplo.ID = 10; exemplo.Nome = "Homem Aranha"; exemplo.Exemplo. InsertOnSubmit (exemplo); Console.WriteLine(); Console.WriteLine(exemplo.GetChangeSet().ToString()); exemplo.SubmitChanges() Console.Write("Pressione algo para continuar . . . "); Console.ReadKey(true); } } } |
Dessa forma efetuamos uma revisão sobre o DataContext do LINQ to SQL e suas principais características. Até o presente momento ele continua sendo uma boa alternativa para acessar e efetuar o mapeamento objeto relacional quando estamos usando um banco de dados SQL Server.
Eu sei é apenas LINQ to SQL, mas eu gosto...
José Carlos Macoratti