2015-01-15 54 views
2

我試圖修復一些執行不當的Linq查詢,但林用語法有問題。我比Linq更擅長SQL。Linq - 用於查詢運算符的不受支持的超載'Where'使用謂詞

當前的工作版本只使用連接,但這是不合適的,因爲它返回的是多個行,然後DISTINCTed。我想將連接轉換爲EXISTS子句。當我向Where子句中添加一個謂詞時,它幾乎可以工作,但窒息。代碼編譯,但我得到了上述錯誤。 SO上有類似的錯誤消息,但它們似乎都在處理稍微不同的情況。

此代碼:

query = from contact in query 
     where Context.TblJobToBrandLink.Join(Context.TblBrandSpends 
                //.Where(spendExpression) 
                .Where(x => x.IntBrandiD != 0), 
              x => x.IntBrandId, 
              y => y.IntBrandiD, 
              (x, y) => x 
              ).Any(jobToBrand => jobToBrand.IntJobId == contact.IntJobId) 
     select contact; 

產生的SQL正是我的預期。

如果我用.Where(spendExpression)取消註釋行,我會得到不受支持的重載錯誤。

spendExpression的類型是Linq.Expressions.Expression < Func鍵< TblBrandSpend,布爾>>

它使用連接工作在版本:

query = from contact in query 
     join jobToBrand in Context.TblJobToBrandLink on contact.IntJobId equals jobToBrand.IntJobId 
     join brandSpend in Context.TblBrandSpends.Where(spendExpression) on jobToBrand.IntBrandId equals brandSpend.IntBrandiD 
     where brandSpend.IntBrandiD != 0 
     select contact; 

任何想法?

+0

難道你不能把兩個子句放在單個Where和&&他們嗎? – JBC 2015-01-15 19:29:48

+0

我也嘗試過 - 不幸的是,lambda類型表達式和謂詞類型表達式不能以這種方式使用。 – user3592246 2015-01-15 19:34:57

+0

特別是謂詞類型似乎有問題 - 如果我整理數據庫,我可以刪除其他Where子句,因爲無論如何都不應該有ID 0的任何品牌,但我們打算稍後再做該項目,因爲速度是一個更緊迫的問題。 – user3592246 2015-01-15 19:36:24

回答

2

我可以在類似的查詢表達式中重現此操作。異常的堆棧跟蹤看起來是這樣的:

在System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression MC)
在System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression MC)
在System.Data.Linq.SqlClient.QueryConverter.VisitInner(表達式節點)
在System.Data.Linq.SqlClient.QueryConverter.VisitWhere(表達式序列,LambdaExpression謂詞)
...
System.Collections中在.Generic.List 1..ctor(IEnumerable 1集)
在System.Linq.Enumerable.ToList [TSource](IEnumerable`1源)

所以它是LINQ到SQL表達式訪問者絆倒一些意想不到的複雜性。這意味着這只是一個錯誤,你必須解決它。

什麼工作(對我來說)是直接使用表達式:

query = from contact in query 
     where Context.TblJobToBrandLink 
        .Join(Context.TblBrandSpends 
        .Where(x => ...) // spendExpression's Expression here 
        ... 

或服用部分Context.TblBrandSpends.Where(spendExpression).Where(x => x.IntBrandiD != 0)查詢外:

var brandSpends = Context.TblBrandSpends 
         .Where(spendExpression) 
         .Where(x => x.IntBrandiD != 0); 

query = from contact in query 
     where Context.TblJobToBrandLink 
        .Join(brandSpends, 
         x => x.IntBrandId, 
         y => y.IntBrandiD, 
         (x, y) => x) 
        .Any(jobToBrand => jobToBrand.IntJobId == contact.IntJobId) 
     select contact; 

它工作在實體框架,順便說一句。

+0

這實際上對實體框架的瞭解非常有用 - 我基本上重做了應用程序的整個搜索引擎,所以現在可能是考慮將數據層移到EF的理想時間。 – user3592246 2015-01-15 19:48:07

+0

我使用了你給出的底部例子,它完美的工作!非常感謝您的幫助。 – user3592246 2015-01-16 09:21:20

相關問題