2016-04-19 86 views
2

使用Linq to Entities,當我對用書寫的LINQ語句創建的Linq對象執行Where lamba表達式時,where子句不工作。Where子句不適用於LINQ IQueryable查詢

這不起作用。查詢執行,但結果未經過濾返回。

var myQuery = (from l in db.MyTable 
        select l); 
myQuery.Where(r => availableStatusList.Contains(r.Status)); 
var myObj = myQuery.ToList(); 

這是行不通的。查詢執行,AND結果返回正確過濾。

var myQuery = (from l in db.MyTable 
        select l).Where(r => availableStatusList.Contains(r.Status)); 
var myObj = myQuery.ToList(); 

據我所知,這兩個應該返回相同的結果。爲什麼第一個人不聽Where條款?

+3

你沒」把它分配回myQuery。 Where子句創建一個新的對象,它不會改變現有的對象。 –

+0

嘗試把'where'換成原始格式(不是從標準格式到內聯格式):從db.MyTable中的l where availableStatusList.Contains(l.Status)select l ;.我很好奇,看看它是否會改變它。 – BlackjacketMack

回答

5

A Where子句在調用時不會創建新對象;它通過將集合包裝在最終將運行的過濾器中來將過濾器應用於現有集合。但是,由於它是一個純函數,因此該過濾器的返回值需要返回到原始參考myQuery,這就是爲什麼第二個示例正常工作的原因......您已將結果通過Where()子句鏈接回myQuery。您返回已過濾的集合,使用ToList()實現延遲查詢。

在第一個示例中,假設過濾器直接應用於集合,但這不是LINQ的工作方式,因爲過濾器在調用函數時不會立即修改集合。相反,它只應用一個謂詞,只要它被「附加」到原始的Queryable集合上並且您用ToList()解決了查詢。

將延期執行視爲一系列承諾有時會更容易。

如果我給你一美元,你有一美元。如果我拿25美分的稅,我已經立即解決了我們的交易(查詢)。

但是,如果我保證在星期二給你一美元,我已經退回Queryable<T>承諾

現在和週二之間可能會發生多個事件。我可以鏈接一個過濾器(25美分),一個口香糖過濾器(25美分)或任何其他過濾器。

但是,我們的簿記系統有一個警告。我們不能只在總承諾金額上撥打.Taxes()(我們的Where條款),並期望其更新。我們必須記錄我們的交易與承諾金額相比,將過濾器返回到原始變量,並使用與我們承諾的金額相對應的交易進行更新。

myQuery = myQuery.Where(condition); 

上週二,當你來收集您的付款(通過對一系列鏈式承諾/過濾器的調用ToList()),我已經扣除從什麼是承諾,造成了50%的支出發生了什麼。這是延遲執行工作。

+1

我認爲'Where'子句實際上會返回一個新的可枚舉,過濾等。 var list = new List {「hi」,「bye」}; Assert.AreNotSame(list,list.Where(w => w ==「hi」)); – BlackjacketMack

+1

@BlackjacketMack IEnumerable不是IQuerable。更新了重點答案。另外,你的比較是無效的。您的比較類型的列表類型爲IEnumerable,這是無效的。它們不是相同的類型,雖然底層的集合沒有改變。如果我們正在談論「對象」的參考,是的,一個新的參考被創建。如果我們正在使用底層集合來談論「對象」,否則不會創建新集合並返回,直到查詢實現爲止。 –

+0

我看到...所以IQueryable不斷得到修改,但保留了相同的參考?所以如果我要添加額外的子句Assert.AreSame()會傳遞?我的印象是,像IEnumerables一樣,每個附加的linq子句都會返回一個新的和不同的IQueryable,作爲一個裝飾者會有意識地包裝前面的語句。 – BlackjacketMack

3

較短的答案:

爲字符串賦值函數功能類似,您需要分配回變量:

string sample = "text"; 

// this doesn't change sample 
sample.ToUpper(); 

// this one does 
sample = sample.ToUpper(); 

所以,你需要的是:

myQuery = myQuery.Where(...)