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)

domingo, 4 de maio de 2008

“DBMS_SQL package” & “EXECUTE IMMEDIATE” - PL/SQL

“DBMS_SQL package” & “EXECUTE IMMEDIATE”

Aproveitando o gancho deixado pelo comentário do Malta(no post anterior), acho que cabe um exemplo mostrando a aplicação das pls da package “DBMS_SQL” na abordagem de SQL dinâmico no Oracle.

Usando a Package

CREATE OR REPALCE PROCEDURE insert_ZNtable (
ZN_ID NUMBER,
NameZN VARCHAR2) IS
ZNcursor_Manipulador INTEGER;
DynSQLZn VARCHAR2(280);
rows_processed BINARY_INTEGER;

BEGIN
DynSQLZn := 'INSERT INTO MyTableZN VALUES (:ZN_ID, :NameZN)';

-- Ao Abrir o cursor atribui valor para o "Handle" , o cursor ID.
ZNcursor_Manipulador := dbms_sql.open_cursor;

-- efetuando o parse
dbms_sql.parse(ZNcursor_Manipulador, DynSQLZn,
dbms_sql.native);

-- fazando o BIND_VARIABLE
dbms_sql.bind_variable
(ZNcursor_Manipulador, ':ZN_ID', ZN_ID);
dbms_sql.bind_variable
(ZNcursor_Manipulador, ':NameZN', NameZN);

-- Executando o cursor
rows_processed :=
dbms_sql.execute(ZNcursor_Manipulador);

-- Fechando o cursor
dbms_sql.close_cursor(ZNcursor_Manipulador);

END;


Usando SQL dinâmico nativo

CREATE PROCEDURE insert_ZNtableExecuteImm(
ZN_ID NUMBER,
NameZN VARCHAR2) IS
DynSQLZn VARCHAR2(280);

BEGIN
DynSQLZn := 'INSERT INTO MyTableZN VALUES (:ZN_ID, :NameZN)';
-- parse e execução no mesmo comando
EXECUTE IMMEDIATE DynSQLZn
USING ZN_ID, NameZN;

END;

Artigo completo (View Full Post)

SQL dinâmico no Oracle

Existe alguma forma de criar dinamicamente um comando SQL, tanto DML quanto DDL, no Oracle?

Sim, é possível. A partir da versão 8i podemos usar o "EXECUTE IMMEDIATE" statement para executar um comando SQL montado em tempo de execução. Essa funcionalidade foi introduzida para substituir o “DBMS_SQL package”. Veja alguns exemplos abaixo:

-- Executando comando DDL “Create”
EXECUTE IMMEDIATE 'CREATE TABLE MyZNTable (ZN_ID NUMBER, ZNDescricao Varchar2(30))';

--- executando comando DML “INSERT”
EXECUTE IMMEDIATE 'insert into MyZNTable values (1, ''ZNteste'') ’;



Esse comando é um recurso nativo do Oracle para abordagem de SQL dinâmico, apropriado para tuning pois reduz overhead, otimiza a performance do comando SQL. Considerando que, Comandos SQL criados e executados dinamicamente apresentam overhead em performance. Utilização do comando "EXECUTE IMMEDIATE" reduz este overhead e proporciona maior performance.
Através dessa técnica podemos também usar placeholders para bind.
O que é placeholder? R - Um placeholder é um identificador não declarado que vai servir como parâmetro, cujo o valor será atribuído dinamicamente. O compilador SQL vai entender o identificador porque ele estará marcado com o prefixo, o sinal de “:” (dois pontos).

DECLARE
V_NUM_CONTRATO varchar2(20) := 'ZN1000';
V_NUM_GUIA varchar2(10) := '3000ZN';
ZnSQL_TMP VARCHAR2 (100);
BEGIN
-- Busca ASSOCIADO, DATA DE CADASTRO, e ORIGEM
ZnSQL_TMP := ' SELECT
DATA_CADASTRO, COD_ASSOCIADO, ASSOCIADO_ORIGEM
FROM
ASSOCIADOS
WHERE
NUM_CONTRATO = :NUM_CONTRATO AND
NUM_GUIA = :NUM_GUIA AND
ROWNUM = 1';

EXECUTE IMMEDIATE ZnSQL_TMP
USING V_NUM_CONTRATO
, V_NUM_GUIA;

END;



Acredito que isso pode facilitar muito o trabalho de desenvolvedor. Portanto, vejamos maiores detalhes sobre a sintaxe desse comando:

EXECUTE IMMEDIATE ZNSQL_string
[INTO {variável[, variável]...
| record}]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...];

Analisando a sintaxe:

ZNSQL_string : Trata-se de uma string com comando SQL construído dinamicamente, conforme exemplificamos anteriormente. Essa string pode conter qualquer comando SQL sem o terminador. Comandos DML “SELECT” não devem retornar mais de uma linha. A string também pode conter placeholders (exemplo: :ZN_ASSOCIADO) e bind_arguments. Um detalhe importante, caso o camando SQL na string for uma chamada a uma procedure ou function (ou seja, uma PL/SQL) é necessário o emprego de “begin” e “end”.

INTO (palavra reservada): Indica quais variáveis (uma ou mais) cujos valores selecionados, em uma consulta, serão atribuídos. O record é um TYPE ou %ROWTYPE definido pelo usuário. Ele pode receber uma linha inteira retornada por uma consulta. Atenção, esta cláusula é opcional. É utilizada somente quando a String for uma consulta que retorne somente uma linha. Além disso, tanto a quantidade de variáveis empregadas, quanto a ordem em que elas estarão dispostas no comando, deve respeitar a quantidade e a ordem das colunas retornadas na consulta. Do mesmo modo, o tipo da variável ou registro (record) deve ser compatível com o valor que lhe será atribuído.

USING (palavra reservada): seção onde declaramos os valores atribuídos a cada argumento na bind variables da string. Não é permitido fazer bind para repassar nomes de objetos de um esquema, como nomes de tabelas ou de colunas. Também não é permitido valor booleano ou NULL. Suponha que o código exemplificado abaixo seja o trecho de uma procedure ou function:


SQL_TMP VARCHAR2 (1000);
BEGIN

SQL_TMP := ' SELECT
DATA_REALIZACAO, COD_ASSOCIADO, ORIGEM
FROM
ASSOCIADOS
WHERE
MES_REF = :MES_REF AND
COD_CONTADOR = :COD_CONTADOR AND
NUM_CONTRATO = :NUM_CONTRATO AND
NUM_GUIA = :NUM_GUIA AND
ROWNUM = 1';
BEGIN
EXECUTE IMMEDIATE SQL_TMP
INTO V_DATA_REALIZACAO, V_COD_ASSOCIADO, V_ORIGEM
USING V_MES_REF
, V_COD_CONTADOR
, V_NUM_CONTRATO
, V_NUM_GUIA;
EXCEPTION
WHEN no_data_found THEN
V_DATa_ZN := NULL;
V_NUM_ASSOCIADO_ZN := NULL;
END;

Preciso retornar várias linhas de uma consulta usando SQL dinâmico. Isso é possível?

Como mencionei anteriormente, consultas que retornem mais de uma linha não são suportadas como valor de retorno. Entretanto, existem alternativas: Ou utilizar uma tabela temporária para armazenar os registros, ou ref cursores.

Adiante, pretendo falar mais sobre o emprego do “EXECUTE IMMEDIATE”.

Artigo completo (View Full Post)

sábado, 3 de maio de 2008

SQL - Operador "LIKE" & ESCAPE

Para a utilização do operador “LIKE”, ANSI SQL, usa-se os caracteres coringas ‘_’, ou ‘%’. Veja o exemplo abaixo:

select
*
from (
select
column_value col
from
table(ts.split_varchar2('Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like 'J_n'

Acima, vimos o exemplo do coringa posicional. Ou seja, para posição que o underscore ocupar na substring de busca, no filtro, o compilador irá interpretar que qualquer caractere serve. O nosso filtro busca qualquer string de três caracteres cujo a primeira posição é ocupada pelo “J” e a última pelo “n”, a posição do meio é o coringa, portanto, qualquer caractere serve. Por isso obtivemos como resultado: “Jan” e “Jun”. Vejamos outro exemplo usando o “%”:


select
*
from (
select column_value col
from
table(ts.split_varchar2('Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like 'J%'



Recapitulando, o underscore é um coringa posicional. Veja que, se por exemplo, na cláusula “where” o valor para o filtro for modificado para “like '_a_'” o resultado do select vai ser: Jan, Mar, Mai. Retornará todos os meses que possuírem a letra “a” como segundo caractere. Conforme exemplificado abaixo:


select
*
from (
select column_value col
from table(ts.split_varchar2('Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like '_a_'


O Problema que muitos desenvolvedores eventualmente enfrentam é quando o caractere coringa é justamente o que ele quer usar como filtro. Por exemplo:

select
*
from (
select column_value col
from table(ts.split_varchar2('Jan,Jan_2008,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like '%_%'


Se você tentar encontrar o registro pela presença do caractere “underscore” o resultado do select não será o esperado. Conforme ilustrado abaixo:



Uma solução, é usar a palavra reservada “ESCAPE”. Desta forma você indica ao compilador SQL qual caractere coringa você deseja que ele considere para busca. Exemplo:

select
*
from (
select column_value col
from
table(ts.split_varchar2('Jan,Jan_2008,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like '%@_%' ESCAPE '@'

Para usar corretamente o ESCAPE, você precisa primeiro marcar o coringa com outro caractere o operando do “like”, exemplo: “like '%@_%'”. Em seguida, o operador do ESCAPE identifica o caractere que marcou o coringa. Exemplo: “ESCAPE '@'”.
Agora o resultado do filtro aplicado retornará o que desejamos:


Outro exemplo:


select
*
from (
select column_value col
from table(ts.split_varchar2('Jan,Jan_2008,Fev_%,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like '%@_2008' ESCAPE '@'




Se trocarmos o marcador, de “@” para “/” visando tornar nosso exemplo mais claro. Além disso, vamos testar usar como filtro a presença do caractere “%”. Para isso inclui o elemento “Fev%Wanddjah” no conjunto a ser selecionado.


select
*
from (
select column_value col
from table(ts.split_varchar2('Jan,Jan_2008, Fev,Fev%Wanddjah,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE col like '%/%Wanddjah' ESCAPE '/'


Veja o resultado:




Outra opção para solução seria usar expressões regulares:

select
*
from (
select column_value col
from table(ts.split_varchar2('Jan,Jan_2008, Jan\Fev ,Fev,Fev%Wanddjah,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE REGEXP_LIKE(col,'\')

O ESCAPE do expressões regulares é o “\” .O exemplo acima retorna todos os registros. Para escapar o especial do caractere “\” caso você precise do seu valor literal use o próprio, conforme exemplificado abaixo:
select
*
from (
select column_value col
from table(ts.split_varchar2('Jan,Jan_2008, Jan\Fev ,Fev,Fev%Wanddjah,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez', ','))
) q
WHERE REGEXP_LIKE(col,'\\').


Agora obteremos como retorno apenas: “Jan\Fev”.

O mesmo vale para os demais metacaracteres. Exemplo: “\.”, “\[”, “\]”, “\?”, “\+”, “\{” , “\}”, “\^”, e “\$”.

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br