none
Compiled Query RRS feed

  • Pergunta

  • Gostaria de fazer join entre duas Compiled Query, porém tenho erro de execução, alguem sabem alguma alteranativa?

    public static readonly Func<DevcompyEntities, IQueryable<EstadoEntity>> Estado = CompiledQuery.Compile((DevcompyEntities db) =>
    	from e in db.EstadoEntity
    	select e);
    	
    public static readonly Func<DevcompyEntities, IQueryable<CidadeEntity>> Cidade = CompiledQuery.Compile((DevcompyEntities db) =>
    	from e in db.CidadeEntity
    	select e);
    	
    public static readonly Func<DevcompyEntities, IQueryable<CidadeEntity>> CidadeEstado = CompiledQuery.Compile((DevcompyEntities db) =>
    	from c in Cidade(db)
    	join e in Estado(db) on c.EstadoId equals e.EstadoId
    	select c);
    
    void Main()
    {
    	//Estado(this).Dump();
    	//Cidade(this).Dump();
    	CidadeEstado(this).Dump();
    }
    
    // Define other methods and classes here
    sexta-feira, 26 de outubro de 2012 21:29

Todas as Respostas

  • Olá Pablo,

    Qual mensagem de erro vc esta recebendo?

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    sábado, 27 de outubro de 2012 12:44
    Moderador
  • Não há suporte ao tipo de nó de expressão LINQ 'Invoke' em LINQ to Entities.
    sábado, 27 de outubro de 2012 12:47
  • Uma alternativa, mas não achei boa, seria não usar o CompiledQuery.Compile.

    Seria uma solução, mas em casos de consultas mais caras para a Engine do EF teria uma perca de performance, pois em o Compiled Query o EF não faria chace dessas consultas, pelo menos foi o que consegui entender até agora sobre o Compiled Query. 

    sábado, 27 de outubro de 2012 12:53
  • Olá,

    Realmente acredito que não irá funcionar.

    Duas alternativas são:

    1 - A sua terceira query não ser compilada, assim:

    var query = from c in Cidade(db)
         	    join e in Estado(db) on c.EstadoId equals e.EstadoId
    	    select c;
    .

    2 - Sua query compilada ser assim:

    static readonly Func<DevcompyEntities, IQueryable<CidadeEntity>> CidadeEstado = CompiledQuery.Compile((DevcompyEntities db) =>
    	from c in db.CidadeEntity
    	join e in db.EstadoEntity on c.EstadoId equals e.EstadoId
    	select c);
    .

    A construção de uma query compilada a partir de duas não é possível.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    sábado, 27 de outubro de 2012 21:23
    Moderador
  • é que na realidade o que precisava mesmo era criar querys e poder reaproveitar elas conforme a necessidade.

    porém pelo que andei estudando, se eu criar uma compiled query e utilizar ela num join com uma não compilada, eu perco a performance desta querya compilada, então a real necessidade de querys compiladas é somente na consulta que será chamada pela aplicação. 

    uma alternativa para o que estou tentando fazer seria o seguinte, mas ainda não testei a performance.

    public static readonly Func<DevcompyEntities, IQueryable<EstadoEntity>> Estado = 
    	CompiledQuery.Compile((DevcompyEntities db) =>
    		from e in db.EstadoEntity
    		select e);
    	
    public static readonly Func<DevcompyEntities, IQueryable<CidadeEntity>> Cidade = 
    	CompiledQuery.Compile((DevcompyEntities db) =>
    		from e in db.CidadeEntity
    		select e);
    	
    public Func<DevcompyEntities, IQueryable<CidadeEstadoEntity>> CidadeEstado 
    {
    	get
    	{
    		DateTime now = DateTime.Now;		
    		var cidades = Cidade(this);
    		var estados = Estado(this);
    		Console.WriteLine(DateTime.Now - now);
    		
    		return CompiledQuery.Compile((DevcompyEntities db)=>
    			from c in cidades
    			join e in estados on c.EstadoId equals e.EstadoId
    			select new CidadeEstadoEntity()
    			{
    				EstadoId = e.EstadoId,
    				CidadeId = c.CidadeId,
    				Cidade = c.Descricao,
    				Estado = e.Descricao
    			});
    	}
    }
    
    void Main()
    {
    	//Estado(this).Dump();
    	//Cidade(this).Dump();
    	CidadeEstado(this).Dump();
    }
    
    public class CidadeEstadoEntity
    {
    	public int EstadoId {get;set;}
    	public int CidadeId {get;set;}
    	public string Cidade{get;set;}
    	public string Estado{get;set;}
    }


    fico no aguardo sobre uma análise desta alternativa que proponho para o referido problema em questão.




    • Editado Pablotdv segunda-feira, 29 de outubro de 2012 11:02
    segunda-feira, 29 de outubro de 2012 10:58
  • Oi Pablo,

    Tudo beleza?

    Chegou a testar esta implementação?

    O meu receio de trabalhar desta forma seja que vc execute três queries ao invés de uma. Quando vc executar cada uma das queries compiladas no seu join vc irá no banco de dados duas vezes, pois cada query precisa pegar seus resultados para o join, e então fazer o join entre os dados em memória. Isto é, vc vai acabar executando 3 consultas em uma única consulta, duas no banco de dados e uma em memória.

    Acredito que a solução mais simples realmente seja criar cada query com sua devida estrutura, sem reaproveitar outras queries compiladas.

    Ligue o trace do banco de dados, assim poderá ver se as duas consultas adicionais são executadas.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    terça-feira, 30 de outubro de 2012 10:24
    Moderador
  • Fernando,

    Acredito que não seja executada duas consultas, pois uso como retorno pras minhas querys um IQueryable e pelo que sei, o IQueryable só executa a consulta no banco quando é invocado algum método que precise dos dados do banco, como por exemplo um Count.

    esta é a consulta gerada pelo LINQPad

    SELECT 
    [Extent1].[CidadeId] AS [CidadeId], 
    [Extent2].[EstadoId] AS [EstadoId], 
    [Extent1].[Descricao] AS [Descricao], 
    [Extent2].[Descricao] AS [Descricao1]
    FROM  [dbo].[Cidade] AS [Extent1]
    INNER JOIN [dbo].[Estado] AS [Extent2] ON [Extent1].[EstadoId] = [Extent2].[EstadoId]
    

    para te dar mais informações sobre o que o trace do banco gera, vou precisar de mais uns dias, pois nunca usei este recurso do SQL Server

    terça-feira, 30 de outubro de 2012 18:18
  • Olá Pablo,

    Vc chegou a simular as queries compiladas no LINQPad?

    Se quiser, me mande a base de dados e eu vejo o trace para vc.

    Acredito que infelizmente o EF não seja esperto o suficiente para mestrar o select das duas consultas e gerar uma só =/

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    quarta-feira, 31 de outubro de 2012 00:17
    Moderador
  • Desculpa Fernando, mas não tenho como disponibilizar a Base de Dados para você.

    Assim que tiver notícias do trace postarei aqui para esclarecermos esta dúvida.

    quarta-feira, 31 de outubro de 2012 11:23