簡體   English   中英

無法翻譯 LINQ 表達式,將在本地計算

[英]The LINQ expression could not be translated and will be evaluated locally

我在 EntityFramework Core 中收到此警告有什么問題?

我已經將 MSSQL 數據庫設置為區分大小寫。

Latin1_General_100_CS_AS

var test = await _context.Students
                .FirstOrDefaultAsync(m => m.LastName.Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase));

Microsoft.EntityFrameworkCore.Query:Warning:無法翻譯 LINQ 表達式 'where [m].LastName.Equals("ALEXANDER", InvariantCultureIgnoreCase)',將在本地進行評估。

您必須了解IEnumerableIqueryable之間的區別。

一個IEnumerable對象表示一個對象序列。 它包含所有要枚舉的序列:你可以請求序列的第一個元素,一旦你有了一個元素,你就可以請求下一個元素,只要有下一個元素。

一個IQueryable對象看起來像一個 IEnumerable,但是,它並不代表一個可枚舉的序列,它代表了獲得一個 IEnumerable 序列的潛力。

IQueryable 對象包含一個Expression和一個Provider Expression是一個通用描述,表示必須查詢的內容。 Provider知道誰將執行查詢(通常是數據庫管理系統)以及使用什么語言與此 DBMS 通信(通常是 SQL)。

如果您開始枚舉 IQueryable,或者顯式使用GetEnumeratorMoveNext ,或者通過調用 foreach、ToList、Max、FirstOrDefault 等隱式調用,這將在內部調用 GetEnumerator 和 MoveNext,則表達式將發送到提供者,提供者會將其翻譯成SQL 並從 DBMS 獲取數據。 獲取的數據以 IEnumerable 的形式返回,其中調用 GetEnumerator 和 MoveNext。

因此,在調用 GetEnumerator 和 MoveNext 之前不會執行查詢。

這和我的問題有什么關系?

實體框架只能將類和方法轉換為它知道的 SQL。 實體框架不知道您自己的功能。 事實上,有幾個 LINQ 功能是實體框架不支持的。 請參閱支持和不支持的 LINQ 方法

不支持的方法之一是String.Equals(string, StringComparison) 如果你使用這個函數,編譯器不會抱怨,因為編譯器不知道你的實體框架版本支持哪些函數。 因此,您在編譯時不會看到此錯誤,您會在運行時看到它。

該錯誤告訴您在調用函數之前將首先獲取數據。 這可能會導致低效行為。

您的 LINQ 語句等於(省略異步等待,不是問題的一部分)

var test = dbContext.Students
    .Where(student => student.LastName.Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase))
    .FirstOrDefault();
    

由於無法使用 Equals,因此警告說數據是在執行 Where 之前在本地獲取的。 因此,可能有幾個不會通過 Where 的項目將從 DBMS 轉移到您的本地進程。

如果您的數據庫可以忽略大小寫敏感,請考慮將代碼更改為:

var test = dbContext.Students
    .Where(student => student.LastName == "ALEXANDER")
    .FirstOrDefault();

這將產生類似於以下內容的 SQL 語句:

SELECT TOP 1 * from myDatabase.Students where LastName = "ALEXANDER"

(不確定這是否是正確的 SQL,因為我使用實體框架,所以我的 SQL 有點生疏。我想你會明白的)

EntityFramework 無法將Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase)轉換為 SQL,因此它會將所有 Student 表加載到內存中,然后搜索滿足等式的第一個條目。

在最后調用 ToListAsync 調用之前以錯誤的順序查詢我的 LINQ 方法,我得到了這個錯誤。

這是為我引發此錯誤的代碼:

var sideeffects = await Context.SideEffects.Include(x => x.Language)
.Select(x => new SideEffect() { Name = x.Name, Language = x.Language, CleanName = x.CleanName, Id = x.Id, SideEffects = x.SideEffects, Related = x.Related, DrugSideEffects = x.DrugSideEffects })
.Where(x => !x.IsDeleted).ToListAsync();

在 select 和 include 之后調用 where 會搞砸查詢並創建此錯誤。 當我將 where 子句移到開頭時,它清除了錯誤並允許使用所有必填字段成功執行查詢:

var sideeffects = await Context.SideEffects.Where(x => !x.IsDeleted)
.Include(x => x.Language)
.Select(x => new SideEffect() { Name = x.Name, Language = x.Language, CleanName = x.CleanName, Id = x.Id, SideEffects = x.SideEffects, Related = x.Related, DrugSideEffects = x.DrugSideEffects }).ToListAsync();

使用實體框架時要注意 LINQ 查詢的順序——尤其是在使用 Select 或 Include 時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM