![](/img/trans.png)
[英]Foreach throws NullReferenceException on not null IEnumerable with elements
[英]Why filtering this IEnumerable throws an NullReferenceException?
我有一個似乎無法解決的特殊問題。 我很確定這個錯誤來自我對 LINQ 查詢的工作原理缺乏深入了解
以下服務返回產品列表並且工作正常(沒有什么是空的)
IEnumerable<Product> products = await _productRepository.GetProductList();
我已經測試了退回的產品,它們的屬性(例如,名稱、價格、描述)都不是 null。 事實上,我可以將它們展示在桌子上。
但是,如果我嘗試過濾返回的產品,我會收到NullReferenceException
IEnumerable<Product> products =products.Where(x=>x.Name.ToLower().StartsWith(keyword.ToLower())).ToList();
即使我檢查了屬性Name
is not null,上面的代碼也會拋出NullReferenceException
(實際上,沒有什么是 null)
如何解決這個問題?
此代碼無法編譯:
IEnumerable<Product> products = await _productRepository.GetProductList();
IEnumerable<Product> products = products.Where(x=>x.Name.ToLower().StartsWith(keyword.ToLower())).ToList();
所以你需要做一些與你的例子有所不同的事情:
如果你有類似的東西:
IEnumerable<Product> products = await _productRepository.GetProductList()
.Where(x=>x.Name.ToLower().StartsWith(keyword.ToLower()))
.ToListAsync();
...那么這應該編譯。 此語句中的NullReferenceException
可能來自keyword
null。
正如上面的評論中提到的,這是一種非常糟糕的取回數據的方式。 問題是,如果您的存儲庫返回IEnumerable
,它會將所有產品加載到 memory 中,只會讓您的消費代碼過濾到少數幾個。
如果您正在使用單元測試,我建議的存儲庫模式是讓存儲庫返回IQueryable<TEntity>
而不是IEnumerable<TEntity>
以便您的消費代碼可以應用過濾等內容:
消費語句將是相同的:
IEnumerable<Product> products = await _productRepository.GetProductList()
.Where(x=>x.Name.ToLower().StartsWith(keyword.ToLower()))
.ToListAsync();
...除了這種方式, Where
條件將應用於 EF 生成的 SQL,從而實現更高效的查詢。 這需要確保 DbContext 實例的范圍涵蓋調用者和存儲庫。 (例如,通過依賴注入提供並限定在 web 請求的生命周期內)
如果您不使用單元測試,那么存儲庫模式不會添加任何內容,直接使用 DbContext 來生成高效查詢會更有效。
不確定您要如何解決 null 的情況,但我猜您的情況可以假設它不是以關鍵字開頭的。 Null 條件運算符與 null 結合是您最好的選擇。 老實說,您應該始終預期 null 參考並知道您想如何處理它們。 我假設關鍵字是一個常數,但如果不是,也應該檢查 null
products = products
.Where(x => x?.Name?.ToLower().StartsWith(keyword.ToLower()) ?? false)
.ToList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.