2017-05-19 1 views
3

Lorsque MesAno est "" //string.EmptyPourquoi ces paramètres optionnels LINQ WHERE ne fonctionne pas?

 DateTime dateAux; 
     int ano = 0; 
     int mes = 0; 
     if (MesAno.Trim() != "" && DateTime.TryParse("01/" + MesAno, out dateAux)) 
     { 
      ano = dateAux.Year; 
      mes = dateAux.Month; 
     } 


       lista = session.Query<Evidencias>().Timeout(30) 
        .Where(m => m.Produto.Distribuidora.Id == myUser.Terceiro.Distribuidora.Id) 
        //.Where(m => MesAno != "" ? (m.DataInclusao.Year == ano && m.DataInclusao.Month == mes) : true) 
        .Where(m => Produto != "" ? m.Produto.CodigoProduto.Contains(Produto) : true) 
        .Where(m => Titular != "" ? m.NomeTitular.Contains(Titular) : true) 
        .Where(m => Instalacao != "" ? m.CodigoInstalacao.Contains(Instalacao) : true) 
        .Where(m => ano != 0 ? m.DataInclusao.Year == ano : true) 
        .Where(m => mes != 0 ? m.DataInclusao.Month == mes : true) 
        .OrderByDescending(m => m.DataInclusao).Take(3000).ToList(); 

Ensuite, le SQL généré Où est:

where [email protected] and @P3=1 and @P4=1 and @P5=1 and datepart(year, evidencias0_.DataInclusao)[email protected] and datepart(month, evidencias0_.DataInclusao)[email protected] order by evidencias0_.DataInclusao desc',N'@P1 int,@P2 int,@P3 bit,@P4 bit,@P5 bit,@P6 int,@P7 int',3000,1,1,1,1,0,0 

La partie est étranger:

datepart(year, evidencias0_.DataInclusao)[email protected] and datepart(month, evidencias0_.DataInclusao)[email protected] 

Pourquoi pas:

@P6=1 and @P7=1 

Répondre

4

C'est étrange bien sûr, mais personne n'est parfait - la traduction de l'arbre d'expression LINQ en SQL est un sujet assez compliqué, il faut tenir compte de beaucoup de choses et ainsi en manquer certaines qui sont "évidentes" pour les humains. Donc, la traduction n'est pas toujours parfaite, mais dès qu'elle ne génère pas d'exceptions et qu'elle produit le bon résultat, elle devrait être acceptable.

Cependant, vous pouvez facilement aider le traducteur à éviter les paramètres et les conditions redondantes (au moins pour le niveau haut IQueryable<T> comme le vôtre) en écrivant une méthode d'extension Where conditionnelle personnalisée comme ceci:

public static class QueryableExtensions 
{ 
    public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, bool condition, Expression<Func<T, bool>> predicate) 
    { 
     return condition ? source.Where(predicate) : source; 
    } 
} 

vous pourriez donc utiliser:

lista = session.Query<Evidencias>().Timeout(30) 
     .Where(m => m.Produto.Distribuidora.Id == myUser.Terceiro.Distribuidora.Id) 
     .WhereIf(Produto != "", m => m.Produto.CodigoProduto.Contains(Produto)) 
     .WhereIf(Titular != "", m => m.NomeTitular.Contains(Titular)) 
     .WhereIf(Instalacao != "", m => m.CodigoInstalacao.Contains(Instalacao)) 
     .WhereIf(ano != 0, m => m.DataInclusao.Year == ano) 
     .WhereIf(mes != 0, m => m.DataInclusao.Month == mes) 
     .OrderByDescending(m => m.DataInclusao).Take(3000).ToList(); 

et le SQL généré aura pas @ P4, P5 @, @ P6, P7 @ paramètres et conditions étranges.

+0

réponse impressionnante. facile, simple, rapide et parfait. Quelle est la meilleure façon de mettre cette classe dans mon projet? Un fichier par classe d'extension dans un paquet? Ou un fichier de classe LinqExtension avec cette classe et d'autres extensions Linq class ??? – MarcioAT

+0

Vous êtes les bienvenus, heureux que cela a aidé :) En ce qui concerne la question, c'est une question de préférence personnelle/style. J'ai habituellement une classe (fichier) comme celle-ci avec beaucoup de mes propres extensions et je l'inclue (copie) dans tout projet dont j'ai besoin. Encore une fois, c'est à vous de décider - utilisez ce qui vous convient dans vos pratiques de codage actuelles :) –