2017-05-19 22 views
3

當MesAno是 「」 //string.Empty爲什麼這個可選參數LINQ WHERE不工作?

 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(); 

然後生成的SQL WHERE是:

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 

陌生人的部分是:

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

爲什麼不這樣:

@P6=1 and @P7=1 

回答

4

當然很奇怪,但沒有人是完美的 - 將LINQ表達式樹翻譯成SQL是相當複雜的主題,必須考慮很多事情,因此可能會錯過一些對人類來說「顯而易見」的東西。所以翻譯並不總是完美的,但只要它不產生異常,併產生正確的結果,它應該是可以接受的。

但是你可以很容易地編寫這樣一個自定義的條件Where擴展方法幫助譯者避免多餘的參數和條件(至少在頂級IQueryable<T>像你這樣):

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; 
    } 
} 

,所以你可以使用:

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(); 

並且生成的SQL不會有@ P4,@ P5,@ P6,@ P7參數和奇怪的情況。

+0

真棒回覆。簡單,簡單,快速和完美。 將這個課程放在我的項目中的最佳方式是什麼?一個包中包含一個擴展類的文件?或者一個LinqExtension類文件與這個類和其他擴展Linq類? – MarcioAT

+0

歡迎您,很高興它幫助:)關於這個問題,這是一個個人喜好/風格的問題。我通常有一個這樣的類(文件)與許多我自己的擴展,並將其包含(複製)到我需要它的任何項目。再次,這取決於你 - 使用任何適合你當前的編碼習慣:) –