我正在嘗試將 Linq 查詢從 EF Core 2.2 遷移到 EF Core 5.0,它在 2.2 中運行良好
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os", "man" }.Any(j => i.Email.Contains(j))).ToListAsync();
錯誤
The LINQ expression 'DbSet<User>()
.Where(u => string[] { "os", "man", }
.Any(j => u.Email.Contains(j)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
我也試過 new[] { "os", "man" }.ToList()/AsEnumerable()
這也有效
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os" }.Any(j => i.Email.Equals(j))).ToListAsync();
結果查詢
SELECT * FROM User WHERE Email = "os"
但這不等于 (... !Equals(..))不起作用
var foo = await _baseRepository.GetQueryable<User>().Where(i => new[] { "os" }.Any(j => !i.Email.Equals(j))).ToListAsync();
我也試過 StartsWith/EndsWith 但我得到了錯誤
相關問題:Entity Framework 3.0 Contains 不能像在 EF Core 2.2 中那樣在 SQL 中進行轉換
uj5u.com熱心網友回復:
不久前(2 年);但是很多 LINQ 陳述句從 2.2 到 3.0。您的鏈接列出了原因(如果 Core 3 無法將 LINQ 轉換為 SQL 陳述句并且需要將記錄拉入記憶體而無需明確,則會引發例外ToEnumerable())和建議的解決方案。
所以,不清楚你在問什么。不幸的是,這些錯誤只出現在運行時;所以你需要遍歷所有這些并且 - 最好 - 使用映射到 SQL 的 LINQ 選項;或者 - 如果不可能 - 顯式呼叫ToEnumerable()
如果您需要在升級前修復它們,您可以撥打電話DbContext:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder
.ConfigureWarnings(warnings => warnings.Log(RelationalEventId.QueryClientEvaluationWarning));
uj5u.com熱心網友回復:
如前所述,這在 EF Core 2.2 中有效,因為它們允許客戶端評估,這有效地執行了一個大的“選擇 *”,或者至少應用了他們可以進行的過濾,然后在記憶體中進行不受支持的評估。
在 EF Core 2.2 中的示例中:
var foo = await _baseRepository.GetQueryable<User>()
.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
在 EF Core 5 中是這樣的:
var foo = await _baseRepository.GetQueryable<User>()
.ToListAsync() // <- materialize for client-side evaluation.
.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
**免責宣告:我不是 100% 確定它甚至有效。您可能需要ToListAsync()在 Get all 上等待,然后將過濾作為單獨的操作進行。
var users = await _baseRepository.GetQueryable<User>()
.ToListAsync(); // <- materialize for client-side evaluation.
var foo = await users.Where(i => new[] { "os", "man" }
.Any(j => i.Email.Contains(j)))
.ToListAsync();
雖然 EF 可以理解string.Contains(),但它無法.Any()針對記憶體中的集決議它。雖然這肯定不理想,因為您在過濾之前加載所有用戶。
要修復它以便 EF 可以翻譯它是這樣的:
var foo = await _baseRepository.GetQueryable<User>()
.Where(i=> i.Email.Contains("os")
|| i.Email.Contains("man")
.ToListAsync();
但是,如果您希望更加動態,例如讓記憶體串列由變數/可配置集組成,那么您需要查看 Dynamic Linq。( https://dynamic-linq.net/ ) 具體來說,它是 Nuget 包,可幫助您構建 EF 可以執行的運算式。這將允許您從一組值動態組合一個 OR 運算式,作為Where子句的一部分執行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/350460.html
上一篇:EFCore支持欄位字串陣列
