Mostrando postagens com marcador Linq. Mostrar todas as postagens
Mostrando postagens com marcador Linq. Mostrar todas as postagens

segunda-feira, 23 de junho de 2008

Linq to SQL - Working with Databases

Clique aqui para ver a versão em português deste post

In this post I continue to show the Linq technology. This tiime we'll see how it's used to access and manipulate data in relational database tables.

In order to use Linq with databases we need to establish a relationship between the business objects in our software and the database tables. To achieve this we use the class/attributes mapping.

This mapping is simple: We create a class that represent a database table and in this class we set which table it is mapped to. In the attributes we set to which database fields they're mapped.

In the current version, Linq only supports the MS SQL Server, but there are already many developers out there working on solutions to cover other RDBMSs too.

To begin let's show a table in the database: Produtos

CREATE TABLE [dbo].[Produtos](
[ProdutoID] [uniqueidentifier] ROWGUIDCOL
NOT NULL CONSTRAINT [DF_Produtos_ProdutoID] DEFAULT (newid()),
[Descricao] [nvarchar](100) COLLATE Latin1_General_CI_AS NOT NULL,
[Preco] [decimal](10, 2) NOT NULL,
[Saldo] [int] NOT NULL,
[Versao] [timestamp] NOT NULL
)


Let's pay close attention at the column Versao, type timestamp. This datatype stores the record version. This is very useful to work with optimistic updates and concurrency issues and Linq makes good use of it.

Before we advance, insert some records in this table.

Now let's create a class that uses this table. In order to use Linq to SQL we need to add reference to the assembly System.Data.Linq to the project. Here is the code:

using System;
using System.Data.Linq.Mapping;

[Table(Name="Produtos")]
class Produto {

[Column(IsPrimaryKey = true,
IsDbGenerated = true,
AutoSync = AutoSync.OnInsert)]
public Guid ProdutoID { get; set; }

[Column(CanBeNull = false)]
public string Descricao { get; set; }

[Column(CanBeNull = false)]
public decimal Preco { get; set; }

[Column(CanBeNull = false)]
public int Saldo { get; set; }

[Column(IsDbGenerated = true,
IsVersion = true, AutoSync = AutoSync.Always)]
public System.Data.Linq.Binary Versao { get; set; }
}


Now let's create a Linq query in this database table. Up until here we just defined the entity and attributes mapping, but we didn't define anything about the database itself. How do we do that?

There is an object in Linq called DataContext. We can think of it more like a database connection in other technologies, but it hardly acts like. It does so much more! It's responsible for the database connection, making and the exectution of the queries, mapping, record updates and even transactions and record concurrency!

We just need to create a instance and it does everything on its own. In other words, we don't need to make code to open or close connection, build string queries and treat results anymore. Let's see the code:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
var Produtos = db.GetTable<Produto>();

var qry =
from p in Produtos
orderby p.Descricao
select p;

foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


What we've done:

- Created a DataContext to connect to the database;
- Created a local variable to represent our mapped table;
- Built the query;
- Display the results;

The wonder of wonders is: Will the DataContext retrieve the entire Produtos table when we create the local variable Produtos? Answer is no! Then, will it occur when we create the qry? Nope. So, where is it?

One of the coolest things in Linq is the ability to send the query to the database only at the moment its data is actually required. In our case, in the foreach loop. That query returned an instance of IOrderedQueryable that seems like a List. But it isn't quite a common list. When its data is required the DataContext build a query based on its definition and send the query to the database and then convert the resultset in an object list, thanks to the mapping features. This technique is called Deferred execution.

How would we do in order to open connection, build a parametrized query and convert the resultset in a list of instances of our business object? And all other tables?

I'll change the code a bit and add some verbose. The DataContext has a property called Log that allows us to view the DataContext's log:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
db.Log = Console.Out;

Console.WriteLine("** Pegando a tabela Produtos");
var Produtos = db.GetTable<Produto>();

Console.WriteLine("** Criando a query");
var qry =
from p in Produtos
where p.Descricao.Contains("a")
orderby p.Descricao
select p;

Console.WriteLine("** Começando a iteração");
foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


Here's the console output:

** Pegando a tabela Produtos
** Criando a query
** Começando a iteração
SELECT [t0].[ProdutoID], [t0].[Descricao], [t0].[Preco], [t0].[Saldo], [t0].[Ver
sao]
FROM [Produtos] AS [t0]
WHERE [t0].[Descricao] LIKE @p0
ORDER BY [t0].[Descricao]
-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [%a%]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

Caderno Universitário 500 folhas, 7,90, 50
Caneta BIC, 1,99, 25
Lapiseira 0,7mm, 5,00, 10
Pasta polionda A4, 2,40, 6


The DataContext produces a query with parameters, instead of concatenate the criteria and build one simple query string. This is very nice, because the RDBMS can make an execution plan for this query and use the same play every time we run this query, even with different parameter values. It means better performance.

Well, that's it for this post, but Linq to SQL goes way further than this. In the next issue I'll write about CRUD operations with Linq to SQL. Thnnk you and take care.

Artigo completo (View Full Post)

Linq to SQL - Trabalhando com bancos de dados

Click here to see this post in English

Neste post vou continuar a mostrar sobre a tecnologia Linq. Desta vez veremos como ela é usada para acessar e manipular dados em tabelas de bancos de dados relacionais.

Para habilitar Linq para acessar bancos de dados nós precisamos primeiro estabelecer relações entre os objetos de negócio do nosso software e as tabelas do banco de dados. Para isso usamos mapeamento de classe/abtributos.

Este mapeamento é simples: Nós criamos uma classe que representa uma tabela do banco de dados e nesta classe nós indicamos qual tabela do banco de dados ela representa. Nas propriedades desta classe nós marcamos quais propriedades representam quais campos da tabela.

Na versão atual Linq suporta apenas o MS SQL Server, mas há desenvolvedores por aí que já estão trabalhando no suporte a outros bancos também.

Para começar vamos mostrar uma tabela no banco de dados: Produtos

CREATE TABLE [dbo].[Produtos](
[ProdutoID] [uniqueidentifier] ROWGUIDCOL
NOT NULL CONSTRAINT [DF_Produtos_ProdutoID] DEFAULT (newid()),
[Descricao] [nvarchar](100) COLLATE Latin1_General_CI_AS NOT NULL,
[Preco] [decimal](10, 2) NOT NULL,
[Saldo] [int] NOT NULL,
[Versao] [timestamp] NOT NULL
)


Atenção especial à coluna Versao, do tipo timestamp. Esta coluna armazena a versão do registro. Ela é útil para efeitos de atualizações otimistas e concorrência e Linq faz ótimo uso dela.

Antes de continuar insira alguns registros nesta tabela.

Agora vamos codificar uma classe que faça uso desta tabela. Para utilizar Linq devemos adicionar referência no projeto para o assembly System.Data.Linq. Abaixo segue o código da classe:

using System;
using System.Data.Linq.Mapping;

[Table(Name="Produtos")]
class Produto {

[Column(IsPrimaryKey = true,
IsDbGenerated = true,
AutoSync = AutoSync.OnInsert)]
public Guid ProdutoID { get; set; }

[Column(CanBeNull = false)]
public string Descricao { get; set; }

[Column(CanBeNull = false)]
public decimal Preco { get; set; }

[Column(CanBeNull = false)]
public int Saldo { get; set; }

[Column(IsDbGenerated = true,
IsVersion = true, AutoSync = AutoSync.Always)]
public System.Data.Linq.Binary Versao { get; set; }
}


Agora vamos criar uma query Linq nesta tabela do banco. Até aqui nós definimos o mapeamento da entidade e dos campos, mas nós não definimos nada sobre o banco de dados. Como faremos isso?

Há uma classe em Linq chamada DataContext. Podemos pensar nela como se fosse um objeto de conexão com um banco de dados, mas o DataContext vai além disso. Ele é responsável pela conexão com o banco de dados, montagem e execução das queries, tratamento dos resultados, cuida das operações de atualização dos registros e até cuida de transações e concorrência de registros!

Para isso só devemos instanciá-lo e ele faz tudo automaticamente! Ou seja, nós não precisamos mais criar códigos para abrir conexão, fechar conexão, montar queries em string, tratar resultados... Vamos ver na prática:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
var Produtos = db.GetTable<Produto>();

var qry =
from p in Produtos
orderby p.Descricao
select p;

foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


Vamos repassar:

- Criamos um DataContext para conectar ao nosso banco de dados;
- Criamos uma variável local para ser a definição da nossa tabela mapeada;
- Fazemos a query extraindo dados desta "tabela";
- Exibimos os resultados.

A parte mais legal é: Será que o DataContext vai trazer a tabela Produtos inteira quando passar pela linha de código onde criamos a variável Produtos? A resposta é não! Então, quando o banco vai na tabela Produtos? Na linha onde criamos a qry? Também não! Ora, então onde é?

Uma das características mais legais do Linq to SQL é a habilidade de executar a query no banco apenas no momento em que seus dados são utilizados. No nosso caso, no loop foreach. Aquela query produziu a variável qry do tipo IOrderedQueryable que, parece, é uma lista. Tem até foreach! Mas ela não guarda as informações nela no momento em que é instanciada. Quando o software "requer" os dados desta "lista", ela produz uma instrução SQL select e traz do banco os resultados, transformando-os em uma coleção de instâncias da classe Produto, através do mapeamento. Isso é chamado Deferred execution.

Como iríamos fazer para abrir conexão com o banco de dados, criar uma query parametrizada e transformar um resultset de datarows em uma lista de instâncias de Produto? E para todas as outras tabelas?

Para reforçar o que foi dito acima, vamos ver o log do DataContext para ver o que ele faz e como faz. Vou adicionar algumas linhas de código ao nosso exemplo anterior e ele vai ficar assim:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
db.Log = Console.Out;

Console.WriteLine("** Pegando a tabela Produtos");
var Produtos = db.GetTable<Produto>();

Console.WriteLine("** Criando a query");
var qry =
from p in Produtos
where p.Descricao.Contains("a")
orderby p.Descricao
select p;

Console.WriteLine("** Começando a iteração");
foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


Olha aqui a saída do console:

** Pegando a tabela Produtos
** Criando a query
** Começando a iteração
SELECT [t0].[ProdutoID], [t0].[Descricao], [t0].[Preco], [t0].[Saldo], [t0].[Ver
sao]
FROM [Produtos] AS [t0]
WHERE [t0].[Descricao] LIKE @p0
ORDER BY [t0].[Descricao]
-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [%a%]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

Caderno Universitário 500 folhas, 7,90, 50
Caneta BIC, 1,99, 25
Lapiseira 0,7mm, 5,00, 10
Pasta polionda A4, 2,40, 6


A query que o DataContext produziu foi parametrizada, em vez de ter os valores concatenados. Isso é muito bom, porque o SGBD faz o plano de execução e deixa ele em cache, para que outras consultas que apenas tenham parâmetros diferentes usem o plano de execução que já foi calculado, trazendo melhor performance.

Com isso chegamos ao fim da nossa primeira visão sobre Linq to SQL e em outros posts vamos ver sobre as oeprações de CRUD com Linq to SQL. Até lá e muito obrigado.

Artigo completo (View Full Post)

terça-feira, 27 de maio de 2008

Linq to Objects - Parte 2

Click here to read this post in English

Olá a todos. Vou dar continuidade ao post anterior sobre Linq to Objects e mostrar algumas outras funcionalidades desta tecnologia que eu tenho achado tão legal. Espero que vocês também achem legal à medidade que eu vou mostrando as coisas que eu tenho visto e estudado. Vamos nessa!

Nos posts anteriores eu mostrei a sintaxe de query do Linq, mas há uma outra forma de fazer consultas com Linq. Todas as instruções (até mais algumas) que usamos nas queries Linq podem ser representada por chamadas de métodos das classes de coleções. Vamos fazer uma consulta na nossa lista do outro post:

var Meses = new List<string> {
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
};

var MesesComJ =
Meses
.Where(mes => mes.StartsWith("J"))
.OrderByDescending(mes => mes)
.Select(mes => mes);

foreach (var m in MesesComJ) {
Console.WriteLine(m);
}


Esta forma, na minha opinião, não é tão legal quanto a outra, mas com certeza também é legal e também mostra de forma clara o que o código quer recuperar.

Para listas simples o select é opcional, mas apenas na forma de métodos - na sintaxe de query é obrigatório.

Hey, que operador maluco é aquele ali? Qual, o =>? Ele é o operador usado para Lambda Expressions. Ah, legal... Mas o que são Lambda Expressions?

Alguns métodos de objetos aceitam como argumento uma definição de função em vez de um valor fixo. Vamos rever o caso do .Where:

.Where(mes => mes.StartsWith("J"))


Vale lembrar que este é um único parâmetro que está sendo passsado para o método. Quando a função fizer a iteração completa na lista ela vai usar este parâmetro para decidir se o item que está na dada posição vai retornar na lista resultante ou não.

Para isso nós definimos a função ali, na hora, criando a condição de retorno de registro. Mas para criar o filtro nós precisamos do contexto. É aí que entra o operador "goes to" (vai para). Ele serve para indicar qual é o contexto da função que estamos criando. Esta condição vai ser testada para cada item da lista (mes.StartsWith("J")), onde mes é o elemento corrente da lista, ou seja: para cada linha da iteração mes será o item corrente. Este tipo de expressão é comum em linguagens funcionais. Vale lembrar que o nome da variável antes do operador é definida por nós, e o código do outro lado deve usar o mesmo nome.

Há muitas expressões de query em Linq; e mesmo que eu soubesse todas este post seria quilométrico! Vamos aqui ver mais dois interessantes: Skip e Take.

Em C# não há representação para Skip e Take na sintaxe de query, somente em métodos. O Skip serve para "pular" resultados e o Take para "pegar" um certo número de linhas:

var Meses456 =
Meses
.Skip(3)
.Take(3);


O resultado será:

Abril
Maio
Junho


A chamada e a ordem dos métodos já nos diz o que a consulta vai retornar: "Pule 3 itens e pegue 3".

Dá para combinar a linguagem de query e as expressões também:

var MesesCom5Letras = (
from mes in Meses
where mes.Length == 5
orderby mes descending
select mes)
.Skip(1)
.Take(2);


O resultado será:

Junho
Julho


À medida em que eu vou aprendendo coisas novas eu posto aqui para o pessoal do Estação. Até treinem e postem aqui suas experiências também. Um grande abraço e até a próxima.

Artigo completo (View Full Post)

Linq to Objects - Part 2

Clique aqui para ler este post em Português

Hello everyone. I'll continue to talk about Linq to Objects in this post and show some other features present in this technology I have found very nice. I really hope you all like it as I continue to show the things I have seen and learned. Let's get to it.

In the previous posts I've shown the Linq query syntax, but there's another way to query data with Linq. All of the statements (in fact even more than that) we see in the query syntax can be represented by Collections' special method calls. They're called query expressions. Let's take a look at the previous example, this time using the method calls:

var Meses = new List<string> {
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
};

var MesesComJ =
Meses
.Where(mes => mes.StartsWith("J"))
.OrderByDescending(mes => mes)
.Select(mes => mes);

foreach (var m in MesesComJ) {
Console.WriteLine(m);
}


This form, imho, is not as cool as the another one, but it's also nice and shows us clearly what the code is going to get too.

Working with simple lists the select call is optional, but only in query expressions - in query syntax is still mandatory.

Hey, what is that weird operator over there? What, the =>? This is the operator we use for Lambda Expressions. Oh, ok... But, what are Lambda Expressions?

Some object methods take a function definition as an argument instead of a fixed value. Let's see the Where line again:

.Where(mes => mes.StartsWith("J"))


Let's note that there's only one argument passed to the method. When the Where method do the full iteration over the list it'll use the funcion defined in this argument to decide if the item at the given position will return in the result list or not.

For that we define the function right there, on the fly, creating the return condition for the items. But to create a dynamic filter we need a context. And here comes the "goes to" operator. It's used to point out what is the context in the function we're defining. This condition is going to be tested for each item in the main list, where mes is the current item. Use of this kind of expression is common in functional languages. The variable name before the operator is defined by us, and the code on the right side have to use the same name.

There are many query expressions in Linq; and even if I knew all of them this post would take ages! Let's see here other two interesting ones: Skip and Take.

There's no representation for Skip and Take in the query syntax in C#, only via method calls. Well, the Skip "Skips" a given number of items and the Take "Takes" a given number of items of the result.

var Meses456 =
Meses
.Skip(3)
.Take(3);


This'll produce the result:

Abril
Maio
Junho


The order of the methods call already gives us a tip of what's goind to happen: "Skip 3 and take the 3 next".

We can combine the query syntax with query expressions too:

var MesesCom5Letras = (
from mes in Meses
where mes.Length == 5
orderby mes descending
select mes)
.Skip(1)
.Take(2);


Resulting:

Junho
Julho


As I'm lerning new stuff I post here for you guys. Until there practice a bit and post your experiences here too. Thank you for the support and take care.

Artigo completo (View Full Post)

segunda-feira, 26 de maio de 2008

Linq to Objects - Consultando dados em memória

Click here to see the English version of this post

Olá a todos. O assunto deste post continua sobre a tecnologia Linq, mas desta vez vamos ver um segmento específico: Linq to Objects.

Antes de começar vou recomendar a todos o livro sobre Linq que estou lendo agora: Linq in Action, dos autores Fabrice Marguerie, Steve Eichert, Jim Wooley, publicado por Manning. Eu não encontrei literatura em português para Linq, então dois grandes amigos meus (Claudão e Fernandão) me deram de presente de aniversário. Um dos melhores presentes que eu já recebi até hoje hehe. Valeu galera! Além de cobir Linq ainda mostra muito de C# e boas práticas.

Voltando à tecnologia. Esta tecnologia nos permite realizar consultas em coleções de dados em memória. instâncias do tipo array, List e outras que implementam a interface IEnumerable podem ser usados com Linq. Basta adicionar o namespace System.Linq no nosso arquivo de código que já podemos utilizar o Linq.

Linq to Objects é particularmente útil quando precisamos obter dados de uma coleção em memória e adicionar funcionalidades de filtro e/ou ordenação. Estas tarefas feitas sem o Linq requerem uma boa quantidade de código para ser implementadas usando loops e variáveis temporárias. Outra vantagem de usar o modo de queries do Linq to Objects é a maior legibilidade do código e facilidade de manutenção e depuração, visto que a instrução mostra claramente o que vamos obter como resultado. Vamos a um exemplo prático:

string[] Meses = {"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"};

var MesesComJ =
from mes in Meses
where mes.StartsWith("J")
orderby mes descending
select mes;

foreach (var m in MesesComJ) {
Console.WriteLine(m);
}


O resultado será:

Junho
Julho
Janeiro


Como seria para gerar este mesmo resultado sem Linq? Se quiser se divertir um pouco e praticar algoritmos, fique à vontade :)

Agora imagine se, em vez de um array de strings pudéssemos fazer uma query com uma lista de objetos? E é possível:

class Program {

class Pessoa {
public string Nome { get; set; }
public string Sobrenome { get; set; }
}

static void Main(string[] args) {

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };
var Gerson = new Pessoa { Nome = "Gerson", Sobrenome = "Motta" };

var Pessoas = new List<Pessoa> {Gerson, Felipe};

var qry =
from pessoa in Pessoas
orderby pessoa.Nome
select pessoa;

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.Nome, p.Sobrenome);
}
}
}


Aqui só vou desviar um pouco do Linq para mostrar novos recursos da linguagem C# para quem não conhece. Primeiro, auto propriedades:

public string Nome { get; set; }


Esta implementação cria a propriedade e, por trás das cortinas, cria os campos encapsulados para armazenar os valores das propriedades públicas. Muito útil para aquelas propriedades que são lidas e escritas diretamente nos campos, sem lógica de validação, ao mesmo tempo que deixa preparado para o futuro, sendo necessário somente terminar a implementação porque a propriedade já está definida.

Depois, tipos inferidos pelo compilador:

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };


Nas versões anteriores nós tínhamos que definir o tipo da variável antes de inicializá-la. Com esta nova técnica o compilador infere o tipo da variável de acordo com o valor que é passado na inicialização. Não se engane: a definição de tipo ainda é forte, apenas nós não precisamos repetir o que a inicialização já diz. O compilador mesmo assim infere o tipo de dados correto na variável. Para variáveis declaradas sem inicialização nós ainda devemos definir o tipo previamente.

Por fim, um construtor especial:

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };


Este construtor nos permite criar uma nova instância de uma classe já definindo suas propriedades.

Agora voltando ao Linq. Aqui selecionamos todas as pessoas da lista ordenando pela propriedade Nome. Se quiséssemos, poderíamos adicionar um filtro por nome adicionando uma cláusula where na consulta:

where pessoa.Nome.Contains("xxx")


Legal né. Mas ainda tem mais! Podemos juntar na mesma query coleções de dados relacionados:


class Program {

class Pessoa {
public string Nome { get; set; }
public string Sobrenome { get; set; }
}

class Pet {
public string Nome { get; set; }
public Pessoa Dono { get; set; }
}

static void Main(string[] args) {

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };
var Gerson = new Pessoa { Nome = "Gerson", Sobrenome = "Motta" };

var Meg = new Pet { Nome = "Meg", Dono = Felipe };
var Rex = new Pet { Nome = "Rex", Dono = Gerson };
var Max = new Pet { Nome = "Max", Dono = Gerson };
var Nina = new Pet { Nome = "Nina", Dono = Felipe };

var Pets = new List<Pet> { Meg, Rex, Max, Nina };

var qry =
from pet in Pets
orderby pet.Dono.Nome
select new {
NomeDono = pet.Dono.Nome + ' ' + pet.Dono.Sobrenome,
NomePet = pet.Nome
};

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.NomeDono, p.NomePet);
}

}
}


Agora veremos mais um recurso interessante: Anonymous types.

select new {
NomeDono = pet.Dono.Nome + ' ' + pet.Dono.Sobrenome,
NomePet = pet.Nome
};


Aqui definimos um novo tipo (anônimo porque é definido ao mesmo tempo em que inicializamos as propriedades). Agora temos um objeto com as propriedades NomeDono e NomePet. O compilador define automaticamente os tipos de dados das propriedades de acordo com sua inicialização.

Agora vamos fazer uma pequena totalização. Vamos mostrar o dono e quantos pets ele possui:

var qry2 =
from pet in Pets
group pet by pet.Dono.Nome + ' ' + pet.Dono.Sobrenome into donos
select new {
Nome = donos.Key,
Pets = donos.Count()
};

foreach (var p in qry2) {
Console.WriteLine("Pets de {0}: {1}", p.Nome, p.Pets);
}


Agora nós criamos um grupo na query agrupando pets com a chave sendo o nome do dono. Neste grupo temos a propriedade Key, que representa o que estamos agrupando. Aí projetamos no resultado a chave do grupo e o contador de registros de cada grupo.

Antes de acabar vou fazer somente uma ressalva: Podemos usar estes resultados como fontes de dados para qualquer controle data-aware de WinForms ou WebForms (GridView, por exemplo).

Bem pessoal, acabou ficando com um tamanho legal, mas espero que tenha mostrado a quem ainda não conhecia como o Linq to Objects pode ser uma boa opção para trabalhar com dados em memória em nossas soluções. Grande abraço e até a próxima!

Artigo completo (View Full Post)

Linq to Objects - Querying in-memory collections

Clique aqui para ver a versão em português deste post

Hello everyone. This post's issue continues about the Linq technology, but this we'll see a specific segment: Linq to Objects.

Before we begin, I want to recommend the book about Linq that I'm reading now: Linq in Action, from the authors Fabrice Marguerie, Steve Eichert, Jim Wooley, published by Manning. It's indeed a great book and will cover not only Linq, but C# features and best practices as well.

Let's get back to Linq to Objects. This technology allows us to query in-memory data collections. Instances of type array, List and others that implement the IEnumerable interface can be used with Linq to Objects. You only need to add a using entry to the namespace System.Linq.

Linq to Objects is particularly useful when we need to query, filter and/or order an in-memory data collection. These tasks when done without Linq (traditional ways) require quite a lot of code that uses loops and temporary variables. Another advantage on using Linq is that the code is easier to read, maintain and debug, as the code clearly shows what we'll get as result. Look at the example:

string[] Months = {"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"};

var MonthsWithJ =
from mon in Months
where mon.StartsWith("J")
orderby mon descending
select mon;

foreach (var m in MonthsWithJ) {
Console.WriteLine(m);
}


The result will be:

June
July
January


How would we produce the same result without Linq? If you want to have some fun and practice some algorithms, suit yourself :)

Now, let's say if, instead of an array of strings we could query an Object list? Yeah, it's possible:

class Program {

class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
}

static void Main(string[] args) {

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };
var Gerson = new Person { FirstName = "Gerson", LastName = "Motta" };

var People = new List<Person> {Gerson, Felipe};

var qry =
from person in People
orderby person.FirstName
select person;

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
}
}
}


Now we'll take a little break on Linq to show some of the new C# features for those that doesn't know them yet. First, auto properties:

public string FirstName { get; set; }


This implementation creates the property and, behind the scenes create the encapsulated field to store the property value. Very usefil for those properties that are read and written directly in the fields and don't need any specific validation logic behind them. But, at same time, provide structure to future changes, as the get and set are already there.

Next, type inference

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };


In early versions we had to define the variable type before initialize it. With this new feature the compiler infers the type in the first value assignment. Make no mistake: the type definition is still strong (not variant); we just don't need to explicitly inform the type because the compiler knows it from the assignment. To define a variable without initialize we do need to inform the type.

At last, a special constructor:

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };


This constructor allows us to create an instance of a class setting the properties rigth away.

Now Let's get back to Linq. Here we'll query all people on the list sorting by FirstName. If we wanted, we could add a search criteria by Name adding a where clause:

where person.FirstName.Contains("xxx")


Cool, isn't it? But there's more! We can query related data in more complex collections:


class Program {

class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
}

class Pet {
public string Name { get; set; }
public Person Owner { get; set; }
}

static void Main(string[] args) {

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };
var Gerson = new Person { FirstName = "Gerson", LastName = "Motta" };

var Meg = new Pet { Name = "Meg", Owner = Felipe };
var Rex = new Pet { Name = "Rex", Owner = Gerson };
var Max = new Pet { Name = "Max", Owner = Gerson };
var Nina = new Pet { Name = "Nina", Owner = Felipe };

var Pets = new List<Pet> { Meg, Rex, Max, Nina };

var qry =
from pet in Pets
orderby pet.Owner.FirstName
select new {
OwnerName = pet.Owner.FirstName + ' ' + pet.Owner.LastName,
PetName = pet.Name
};

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.OwnerName, p.PetName);
}

}
}


Now let's see another new interesting feature: Anonymous types.

select new {
OwnerName = pet.Owner.FirstName + ' ' + pet.Owner.LastName,
PetName = pet.Name
};


Here we define a new type (anonymous because it's defined at same time that we set the properties). Now we have an object with properties named OwnerName and PetName. The compiler automatically infers the properties' types according with their initialization.

Now we're goind to do an aggregation. We'll show the owner and how many pets they have:

var qry2 =
from pet in Pets
group pet by pet.Owner.FirstName + ' ' + pet.Owner.LastName into ownerPets
select new {
Name = ownerPets.Key,
Pets = ownerPets.Count()
};

foreach (var p in qry2) {
Console.WriteLine("{0}'s Pets: {1}", p.Name, p.Pets);
}


Now we created a group in the query counting pets with a key being the Owner's name. In this group we have a property named Key, which represents the information we're grouping. Then we project the group key and the group count in the resultset.

Before we finish, let me point out something: We can use these query results as data sources for data-aware controls, such as GridViews on WinForms or WebForms.

Well, it ended up more lengthy than I expected, but i think that it could show some of the power and usefulness of Linq to Objects technique. Thank you all for the support and see you at the next post. Take care!

Artigo completo (View Full Post)

Acesso a dados com Linq

Click here to see the english version of this post

Olá a todos. Peço desculpas pelo tempo em que estive sem postar aqui no blog. Antes de chegar no assunto gostaria muito de mandar um obrigado especial a todos os visitantes do Estação ZN, que está crescendo em acessos cada vez mais. Nós nos sentimos muito orgulhosos e felizes de ver que este conteúdo que nós postamos aqui e que são freqüentemente retirados de conversas e problemas do dia-a-dia está chegando a todos que acessam nosso blog. Se o que é postado aqui consegue ajudar, fazer pensar, ou até mesmo distrair alguém nosso trabalho já valeu a pena.

Para compensar vou postar sobre um assunto que nos (eu e o Gerson) deixou boquiabertos: Linq - Uma nova tecnologia de acesso a dados presente no Visual Studio 2008 e na .Net 3.5.

Linq é sigla para Language-integrated query. Significa que é uma tecnologia (ou melhor, um conjunto delas) que adiciona recursos de consulta semelhantes às queries da linguagem SQL no nível da linguagem (compilador).

O que isso quer dizer? Que esta tecnologia nos permite (entre outras coisas) consultar dados em memória, arquivos XML e até de bancos de dados relacionais de forma declarativa (funcional), ao invés da maneira imperativa tradicional que usamos.

Linq veio também para diminuir uma coisa chamada "impedance mismatch", que representa a diferença entre o modelo de classes/objetos do software e os modelos de entidades/relacionamentos do banco e dos arquivos XML. Explicando um pouco melhor: Vamos partir do seguinte princício: Dados Relacionais <> XML <> Objetos. No software nós utilizamos o modelo POO, com herança, polimorfismo e por aí vai. Os dados que nossos aplicativos geralmente acessam estão representados em forma de tabelas em bancos de dados relacionais ou arquivos XML. Entre estes três mundos nós não temos praticamente nenhuma compatibilidade; até os tipos de dados são diferentes.
Hoje em dia, para trabalhar com estes dados em nossos aplicativos nós precisamos usar as APIs que as linguagens nos fornecem. Mas nós sempre precisamos escrever mais código que deveríamos, e o código que escrevemos para acessar estes dados não representa claramente o resultado que queremos. Isso se deve à maneira imperativa que as linguagens requerem para acesso aos dados.

Ah, Felipe..., ..., ... Ok. Vamos a um exemplo:

Queremos fazer um select no banco de dados. Há algumas pequenas diferenças entre linguagens, mas a idéia é a mesma:


  • 1. Abre conexão com o banco de dados

  • 2. Cria um objeto para realizar a consulta.

  • 3. Passa a consulta SQL para ele.

  • 4. Executa a consulta e retorna para um objeto que armazena o resutset.

  • 5. Libera os recursos e usa o resultset.



Este modelo nos traz a necessidade de implementar, de forma imperativa, o que o sistema deve fazer em cada momento. Também precisamos escrever código para conexão e execução da query, que não faz parte diretamente da lógica e, por fim, temos que enviar a query para o banco como uma string, onde só saberemos se tem algum erro de sintaxe em tempo de execução. Então, quando o banco retornar os resultados teremos que "traduzir" este resultset em objetos para se encaixar ao nosso modelo de classes do programa. Em resumo: muito código e de difícil leitura, manutenção e depuração.

Mas como o Linq é diferente? Primeiro vamos ver os diversos tipos de formas do Linq. Primeiro temos o Linq to Objects, que nos permite selecionar e ordenar e filtrar coleções em memória. Vamos dar um exemplo:

string[] Meses = {
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"};

var MesesComA =
from mes in Meses
where mes.StartsWith("A")
orderby mes descending
select mes;

foreach (var m in MesesComA) {
Console.WriteLine(m);
}


Dê uma olhada na parte onde consultamos o array de string Meses. Neste trecho fazemos uma consulta no array Meses onde trazemos qualquer elemento que comece com a letra A e ordenamos o resultado em ordem decrescente. Desta forma acessamos os dados de forma declarativa, assim como nas linguagens funcionais. Imagine como escreveríamos este código na forma imperativa padrão...

Em Linq to Objects, podemos fazer este tipo de consulta em qualquer classe que implemente a interface IEnumerable (o array implementa essa classe, embora não pareça).

Este modelo de queries pode ser aplicado também em dados do banco de dados e arquivos XML. Mas como? Primeiro vamos falar do banco de dados - não vamos nos aprofundar muito porque o objetivo deste post é mostrar o que é Linq e do que ele capaz.

Nós fazemos consultas em bancos de dados da mesma forma declarativa que consultamos coleções de objetos. Mas Felipe, se eu tiver que trazer uma tabela inteira do banco e ter que transformá-la em array para depois fazer a consulta pode jogar esta tecnologia fora! Com certeza a Microsoft não faria isso com uma tecnologia que visa facilitar a vida dos desenvolvedores. O Linq to SQL funciona com uma outra tecnologia da linguagem: Mapeamento de entidades.

Em Linq to SQL nós temos nossos objetos no programa e os decoramos com atributos especiais de mapemento (Em outros posts eu falo e mostro mais sobre isso). De forma mais simples, nós marcamos nossas classes como "Classes de entidade" do banco de dados e informamos as tabelas e campos que nossos objetos/propriedades representam; então, quando consultamos estes objetos, o Linq monta a query para o banco de dados e "traduz" os objetos e propriedades em tabelas e campos. O Linq trata intrinsecamente todos os processos que são necesários mas não fazem parte da lógia do programa, como conexão com o banco, obtenção de registros e tradução de resultsets em objetos.

Linq to SQL vai além disso, provendo também API de atualização de dados, transação e controle de concorrência.

Linq to XML provê uma API simples e única para consultar e também criar arquivos XML; uma API muito mais simples que as atuais que conhecemos (DOM, XSL, XPath, XQuery). A sintaxe de consulta é muito semelhante à Linq to Objects, e esta padronização é muito boa nós desenvolvedores nos acostumarmos rapidamente.

Como o objetivo deste post é falar sobre uma nova tecnologia e ter uma visão geral, vou deixar os "sabores" específicos do Linq para outros posts. Até lá procurem mais e divirtam-se.

Um grande abraço a todos e até a póxima.

Artigo completo (View Full Post)

Data access with Linq

Clique aqui para ver este post em português

Hello everyone. This is the first post in Estação ZN in English. We decided to give an "English version" to our posts due to the increasing non-Brazilian public of our blog, which we would like say thank you very much. From now on I'll try to make an English translation of every post i make. I ain't a native English speaker, so please bear with me a little bit. :)

Let's get started. In this post I'm bringing an issue that left me and Gerson speechless: A new data access technology present in Visual Studio 2008 and .NET 3.5.

Linq stands for Language-integrated Query. It's a technology (a few of them, in fact) that adds query capabilities at language (compiler) level.

What does it mean? It means that Linq allows us (amongst others things) to query in-memory data, XML files and even relational database tables in a declarative manner (like funcional languages) instead of the traditional, imperative way we're used to.

Linq also came to propose a solution for the "impedance mismatch", that is the difference between the program's object model (OOP) and the relational databases/XML files data model. Going a bit deeper: Let's begin with the principle: Relational data <> XML files <> Objects hierarchy/relationships. At the software we have the OOP model, with inheritance, polimorphism and so on. The data our software usually accesses are represented in relational database tables and XML files. In these worlds we have no compatibility whatsoever; even the data types are different.
In order to work with data nowadays we need to use APIs that the languages provide us. But we always have to write more code than we should, and the code that we write to access the data doesn't clearly represent what we want to do. That is because of the imperative way that the languages require to access and manipulate data on external sources.

Eh..., ..., ... Ok. Here's an example:

We want to query data from a database. There are minor differences between the languages but it all comes down to one path in most cases:


  • 1. Open connection with the database

  • 2. Instantiate an object to execute the query

  • 3. Pass the query as string

  • 4. Send the query to the database and get the resultset

  • 5. Release the resources and uses the resultset



This model comes with the necessity of implement, in a imperative way, what the program has to do at each moment. We also have to write code to explicitly connect to the database and run the query, which isn't part of our program logic, and at last, but not least, we have to code the query as string, not using the compiler's type checking at design time - if our query has any errors, we'll discover it only at run time. Then, when the application retrieve the data from the database we have to manually "translate" the database's resultset into objects. It takes too many "unnecessary" code (I would say code that doesn't belong there) and produces code that is difficult to read, mantain and debug.

But how's Linq different? First, let's see the several "flavors" of Linq. We'll see the Linq to Objects first, which allows us to query, filter and sort in-memory collections. Let's go on a example:

string[] Months = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"};

var MonthsWithA =
from mon in Months
where mon.StartsWith("A")
orderby mon descending
select mon;

foreach (var m in MonthsWithA) {
Console.WriteLine(m);
}


Take a look at the part where we query the string array Months. In this fragment we search the Months array for any month that starts with the letter A and sort the results descending. This way we access the data in a declarative way, like we would do with funcional languages. Imagine how would be the code to achieve the same results in the traditional, imperative way...

In Linq to Objects we can query any object that implements the IEnumerable interface (the array implenents this interface even though it doens't look like).

This querying model can be applied in relational data and XML files too. But how? Let's see the relational database first - We won't dive too deep into it for now because this post's objective is to show what is Linq and what it is capable of.

With Linq to SQL we can query the database in the same declarative way we do on object collections. But Felipe, if I have to retrieve the entire table from the database and convert it into an array before I can use the Linq, then I surely don't want it! For sure Microsoft wouldn't do it with a technology that is intended to make the developers' life easier. Linq to SQL works with another new language enhancement: Entity Mapping.

In Linq to SQL we have the classes in our program decorated with the special Mapping attributes (I'll talk about and show it in another posts). In other words, we'll "mark" our classes as "Entity classes" and inform which tables and fields are related to which classes and properties; and then, when we query these objects, Linq "mounts" the query and retrieve the results into the objects - all thanks to the mapping attributes.

Linq to SQL can do way more than this. It also provides APIs for data updates, transactions and concurrency control. We'll see more of that later.

Linq to XML provides a simple and unified API to query and also create/edit XML files; an API that is way simpler than those we know nowadays (DOM, XSL, XPath, XQuery). The query syntax is very alike to the Linq to Objects, and this is very nice to us developers to get used to quickly.

As the goal of this post being talk about a relatively new technology and have a peek into all this, I'll let the specific "flavors" of Linq to other posts. See you all and have fun.

Thank you for spending time with us, and please excuse me about any English errors, as i'm no native English speaker, and feel free to send any suggestions and even corrections (please correct me!). Bye...

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br