Linq

LINQ, Execução postergada #2

0

Fala Galera, vocês já devem ter lido sobre a execução postergada(lazy-loading) do LINQ. Basicamente o que a execução postergada faz é atrasar a execução até o ultimo momento possível, a execução postergada possui uma forte ligação com outros conceitos como iterator,yield entre outros. Sabendo disso o LINQ atrasa a execução das queries até sua real necessidade, isso pode ser bom ou ruim dependendo do uso. A execução postergada é muito boa no aspecto de carregar somente o que será usado, é ruim quando realizamos muitas operações usando o “.”, isto é, acessando outros objetos e propriedades.. segue o exemplo, o mesmo foi testado no linqpad.

Para esclarecer preciso dizer que o objeto  EventTool possui uma coleção de TicketTool,A query itera sobre eventTool e acessa a propriedade EndDate do TicketTool.

Este código quando executado gera o sql abaixo:

Todas estas queries foram geradas pois o LINQ deixa para trazer p TicketTool quando ele é realmente executado, como chamamos diversas vezes o TicketTool ele tem que disparar várias queries.Temos uma solução simples e classica para isso que é usar o DataLoadOptions, com o dataLoadOptions podemos especificar  quais objetos devem ser carregados juntos. exemplo:

Este código gera o seguinte sql:

O objetivo do post é lembrar que quando estamos executando uma operação sobre um objeto pertencente a uma coleção devemos atentar para o impacto do codigo escrito, sei que o codigo poderia ser escrito de maneira melhor.. mas optei por deixar assim para mostrar o impacto na tradução de código linq para sql.

C# Yield

1

Fala Galera, depois de aprender a usar a keyword let fiquei um tanto quanto interessado em aprender keywords não tanto populares, eis achei a keyword Yield. Li posts super empolgados sobre a keyword e realmente ela é super legal.

Acho melhor ir mostrando o uso e falando das vantagens. A primeira coisa que devemos saber é que o Yield é uma keyword fundamental para trabalhar com Iteradores, veremos também qual é  a sua importacia por tras de tipos que utilizam Iteradores, principalmente os Enumerables.

Um exemplo comum de código é a filtragem de sublistas de acordo com um dado aspecto, estou querendo falar sobre casos como o exemplo abaixo:

ps:Desconsidere as muitas outras opções de realizar a mesma ação

Acho que a intenção do código de exemplo está ok, certo? sendo assim voltando  ao yield a idéia do mesmo é prover uma melhor maneira de trabalhar com iteradores,
então podemos reescrever nosso método da seguinte maneira:

Esta é uma das maneiras de usar o yield. Para entender a logica do funcionamento acima temos que recorrer ao funcionamento dos iteradores, basicamente temos que saber que os mesmos geralmente possui um método Next() ou também chamado de MoveNext(), o que o método next faz é mover o ponteiro para o proximo item a ser ‘retornado”. O que isso tem a ver com o yield? simples! quando nós usamos o yield return não estamos saindo da função, estamos falando que após o return haverá uma pausa, e quando o proximo item for requisitado(MoveNext)a execução continua de onde foi pausada.

Vantagens

  1. Quantidade menor de código
  2. Desempenho aprimorado
  3. Lazy Loading(ainda será explicado)
  4. Demonstrar conhecimento sobre a linguagem

1-Podemos representar o mesmo código de maneira mais simples

2-O codigo com yield tem quase 1/4 do tamanho do mesmo código com sublista quando representado em MSIL

3-O yield é fundamental para a execução postergada, pois o mesmo prove a opção de recuperar a informação apenas no momento de real utilização da mesma. O yield está por baixo de muita coisa do LINQ .

4-Por ultimo, o yield pode ser usado quando você estiver sem papo com a equipe de desenvolvimento :)

O yield ainda pode ser usado com a keyword break, que define o fim da enumeração, você pode encontrar mais informações aqui

fontes:

http://blogs.microsoft.co.il/blogs/shayf/archive/2008/06/06/give-way-to-the-yield-keyword.aspx

http://en.wikipedia.org/wiki/Coroutine

http://startbigthinksmall.wordpress.com/2008/06/09/behind-the-scenes-of-the-c-yield-keyword/

http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html

http://www.informit.com/articles/article.aspx?p=725693&seqNum=3

C# usando keyword let

0

Fala Galera, acho que vocês já precisaram desta “keyword” pelo menos uma vez. Vocês já precisaram repetir uma determinada expressão dentro da query linq? já escrevem o mesmo código várias vezes? caso ainda esteja em dúvida olhe o exemplo de código abaixo

- Desejo fazer o seguinte:

-Somar todos os valores

-Somar todos os valores e adicionar o numero que será exibido

-Somar todos os valores e subtrair o numero que será exibido

13 List<int> lista = new List<int>();

14             lista.Add(1);

15             lista.Add(2);

16             lista.Add(3);

17             lista.Add(4);

18

19

20 var query = from num in lista

21 select new

22                         {

23                             somatorio = lista.Sum(),

24                             numero_somatorio = lista.Sum() + num,

25                             numero_subtracao = lista.Sum() – num

26                         };

No exemplo acima o sum() está duplicado, neste caso podemos usar o operador let. com este operador podemos definir uma variavel que será computada apenas na requisição(lazy loading)

22 var query = from num in lista

23 let soma = lista.Sum()

24 select new

25                         {

26                             somatorio = soma,

27                             numero_somatorio = num + soma,

28                             numero_subtracao = soma – num

29                         };

Sintaxe:let <nomedavariavel> = valor

Agora basta refatorar suas queries e melhorar seu codigo. enjoy!

Criando custom operator no LINQ

0

Fala galera, desta vez vou mostrar como criar um custom operator no LINQ. A necessidade surgiu do seguinte problema. No projeto onde trabalho temos uma classe chamada Parcel(Parcela) esta classe tem um campo chamado dueDate(Data de vencimento), Diversas vezes temos que fazer pesquisa por período para verificar se a parcela está dentro do período especificado. Diversas “telas” tinham este mecanismo de pesquisa e os métodos sempre esperavam duas datas(inicio,fim), Sendo assim criamos um controle para a pesquisa e uma classe para armazenar o intervalo de datas(DateTimeInterval). Desta maneira parte do nosso problema estava resolvido, mas ainda tínhamos algumas condicionais espalhadas pelo sistema(Regra de negócios) para verificar se a parcela estava ou não no intervalo.Sendo assim me ocorreu a idéia de criar um custom operator no LINQ para centralizar esta condicional.

Segue abaixo um exemplo simplorio da criação e uso do customOperator

26 public class Parcel

27 {

28 private DateTime _dueDate;

29 public DateTime DueDate

30 {

31 get { return _dueDate; }

32 set { _dueDate = value; }

33 }

34 }

DateTimeInterval

19 public class Interval

20 {

21 private DateTime _beginDate;

22 private DateTime _endDate;

23 public DateTime BeginDate { get { return _beginDate; } set { _beginDate = value; } }

24 public DateTime EndDate { get { return _endDate; } set { _endDate = value; } }

25 }

CustomOperator:

Herança usando LINQTOSQL

1

O linq oferece suporte ao programador para que o mesmo trabalhe com orientação a objetos.Sendo a herança um dos pilares da poo cabe ao linq também suporta – lá. Bem, eu criei um projeto simplório, com o objetivo de mostrar que realmente podemos usar herança.
Foram criadas três tabelas, Animal, mamífero e ovíparo (não pensei em uma herança mais inteligente para ser implementada).Segue o script de geração das tabelas.


USE [Animal]
GO
/****** Object: Table [dbo].[Animal] Script Date: 08/24/2008 20:03:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Animal](
[AnimalId] [int] NOT NULL,
[Name] [varchar](200) COLLATE Latin1_General_CI_AS NULL,
[weight] [int] NULL,
[Type] [char](1) COLLATE Latin1_General_CI_AS NULL,
[mammalId] [int] NULL,
[oviparousId] [int] NULL,
CONSTRAINT [PK_Animal] PRIMARY KEY CLUSTERED
(
[AnimalId] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

USE [Animal]
GO
/****** Object: Table [dbo].[Mammal] Script Date: 08/24/2008 20:05:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Mammal](
[mammalId] [int] NOT NULL,
[cubPerGrowth] [int] NULL
) ON [PRIMARY]

USE [Animal]
GO
/****** Object: Table [dbo].[Oviparous] Script Date: 08/24/2008 20:05:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Oviparous](
[oviparousId] [int] NOT NULL,
[eggPerGrowth] [int] NULL
) ON [PRIMARY]


Imagens das tabelas:

Agora já possuímos a estrutura de dados necessária.O próximo passo é criar um projeto DataClasses(Add->new Item->LINQTOSQL Classes).Selecione as tabelas e arraste-as para a superfície exibida quando selecionamos o projeto DataClasses

Agora vamos configurar a herança.Clicar na superfície do priojeto dataclasses e selecionar a opção(add->inheritance). Irá aparecer uma opção de confiração, pedindo que sejam selecionadas a classe base e a classe derivada. Como classe base selecionaremos a classe animal e como base a classe ovíparo.Devemos fazer o mesmo para a classe mamífero. Agora a herança existe mas não está configurada, vamos começar pelo relacionamento entre a classe animal e mamífero.clicar no relacionamento e selecionar a opção propriedades.

Base class Discriminator value: qual valor será usado para discriminar a classe base(animal) no nosso caso usaremos a letra ‘a’ animal.
Derived class Discriminator Value: relativo ao valor usado para discriminar a classe derivada. No nosso caso usaremos ‘m’ de mamífero.
Discriminator property: relativo ao campo que será usado para discriminar a herança. No nosso caso será o campo ‘type’
Inheritance default: identifica qual será a herança padrão. No nosso caso selecionaremos animal.

O mesmo processo deve ser realizado para o outro relacionamento entre animal e ovíparo.lembrando que o único valor alterado será a propriedade derived class discrimator value.

Agora já podemos usar nossos objetos com herança.

Execução postergada – Parte 1

0

Fala galera, vocês podem reparar que demorei um pouco para postar(mais que o habitual).Este fato ocorreu pois estou “recomeçando” minha rotina logo o tempo ficou curto.Entretanto vamos ao que realmente importa, mais um post. Desta vez vamos falar sobre um recurso do LINQ originalmente chamado deferred execution(Execução postergada).


Execução postergada: O LinqToSql posterga a execução de uma query até o momento em que a mesma é realmente executada.O que isso quer dizer? Que se você faz um código assim

48 dcDataContext dc = new dcDataContext();

49 dc.Log = Console.Out;

50 var query = from book in dc.Books

51 select book;

52 grdData.DataSource = query;



A query é disparada quando você seta o valor da query no DataSource.Então se você comentar a linha que atribui o valor ao DataSource a linha não é executada? Isso mesmo.Você pode fazer isso setando a propriedade log

Existe outra maneira de executar uma query, ela se chama Execução Imediata.

Pode ser que você queira que a consulta seja registrada imediamente(após sua formação). Bem, você pode forçar tal execução.Usando os métodos ToList(),ToArray(), ToDictionary entre outros você executa a query imediatamente. É importante salientar que se após esta execução você tente usar os operadores padrão do linq(where,group,etc) você estará executando com LinqToObject.É isso mesmo, você gastou mais banda para trafegar com os dados e agora está executando no ‘cliente’ o que poderia ser executado no banco de Dados(SQL)

78 //Execução Imediata usando ToList()

79

80 dcDataContext dc = new dcDataContext();

81 dc.Log = Console.Out;

82 var list = dc.Books.ToList();

83

84 //mesmo sem setar o DataSource a query foi registrada


Bem galera, é isso. Resolvi dividir o post em duas partes, no post final irei explicar como o linq executa isso. Como a execução postergada é possível.



Grande abraço..

Debugando uma query no LINQ

0

Fala galera, aqui na empresa geralmente nós precisamos visualizar o resultado sql gerado por uma query no LINQ.

Código SQl gerado:

Ps: Galera, só para lembrar que o console.Out não funciona no asp.Net.

É isso galera, acho que ainda essa semana postarei sobre como o LINQ executa uma query qualquer.Abraços!!

.NET 3.5 – Métodos de extensão

0

Fala galera, lendo sobre métodos de extensão.Tive uma dúvida interessante.
“Métodos de extensão sobrepõem os métodos de instancia”

Bem, a resposta é não.então quando declaramos um método na classe desejada e temos um método de extensão com a mesma assinatura,Ao executarmos uma chamada ao método de uma instancia da classe o método de instancia será executado.

No exemplo acima o método de extensão foi aplicado a classe Object, logo a classe1 ‘ganhou’ acesso a esse método. porém ao usarmos o method1 o método executado foi o da própria classe1.

LINQ as a remote control

0
“LINQ as a universal remote control”

Fala moçada, a frase é estranha não é? eu li esta afirmação no LINQ em ação. Quem disse isto foi um dos arquitetos do LINQ. Ele relacionou o LINQ com um controle remoto universal pois de acordo com sua ideia o LINQ é capaz de controlar e manipular diversas fontes de dados(data stores). É, a relação é simples não é?! tudo bem, eu achei a frase interessante.É isso moçada.. assim que aprender mais coisas legais posto aqui.Abraços!!

Linq to Sql- Agrupando e retornando outras propriedades

0

Fala Moçada, durante muito tempo aqui na empresa sempre que faziamos uma query(LINQ) e usávamos a cláusula GroupBy tinhamos de colocar um groupBy new e dentro do new colocar todas as propriedades que desejávamos retornar.exemplo:

from bill in Billsgroup bill by new{bill.BillId,bill.DocumentNumber,bill.Description} into gBillselect new{gBill.Key.BillId ,gBill.Key.DocumentNumber,gBill.Key.Description}

Bem, da nova forma as coisas ficam bem mais simples. Quando desejarmos retornar vários campos podemos fazer da seguinte maneira:

from bill in Bills
group bill by bill.BillId into gBill
select new{
bill = from bill in gBill select bill
}

É isso galera espero que este post seja tão interessante para vocês quanto foi pra mim.

Go to Top