查詢的運作方式How Queries Work

Entity Framework Core 使用 Language Integrated Query (LINQ) 查詢來自資料庫的資料。Entity Framework Core uses Language Integrated Query (LINQ) to query data from the database. LINQ 可讓您使用 C# (或您選擇的 .NET 語言),根據衍生內容和實體類別來寫入強型別查詢。LINQ allows you to use C# (or your .NET language of choice) to write strongly typed queries based on your derived context and entity classes.

查詢的生命週期The life of a query

以下是每個查詢所經歷程序的高階概觀。The following is a high level overview of the process each query goes through.

  1. LINQ 查詢會由 Entity Framework Core 所處理,以建置已準備好由資料庫提供者所處理的表示方式The LINQ query is processed by Entity Framework Core to build a representation that is ready to be processed by the database provider
    1. 結果會被快取,因此並不需要在每次執行查詢時進行此處理程序The result is cached so that this processing does not need to be done every time the query is executed
  2. 結果會傳遞給資料庫提供者The result is passed to the database provider
    1. 資料庫提供者會識別查詢的哪些組件可在資料庫中評估The database provider identifies which parts of the query can be evaluated in the database
    2. 查詢的這些組件會轉譯為資料庫特定的查詢語言 (例如,針對關聯式資料庫會轉譯為 SQL)These parts of the query are translated to database specific query language (for example, SQL for a relational database)
    3. 系統會將一或多個查詢傳送到資料庫,並會傳回結果集 (結果是來自資料庫的值,而非實體執行個體)One or more queries are sent to the database and the result set returned (results are values from the database, not entity instances)
  3. 針對結果集中的每個項目For each item in the result set
    1. 如果這是追蹤查詢,EF 就會檢查資料是否代表已存在於內容執行個體變更追蹤器中的實體If this is a tracking query, EF checks if the data represents an entity already in the change tracker for the context instance
      • 如果是,就會傳回現有的實體If so, the existing entity is returned
      • 如果不是,則會建立新的實體,設定變更追蹤,並傳回新的實體If not, a new entity is created, change tracking is setup, and the new entity is returned
    2. 如果這是非追蹤查詢,EF 就會檢查資料是否代表已存在於此查詢結果集中的實體If this is a no-tracking query, EF checks if the data represents an entity already in the result set for this query
      • 如果是,就會傳回現有的實體 (1)If so, the existing entity is returned (1)
      • 如果不是,則會建立並傳回新的實體If not, a new entity is created and returned

(1) 非追蹤查詢會使用弱式參考來持續追蹤已經傳回的實體。(1) No tracking queries use weak references to keep track of entities that have already been returned. 如果先前具有相同身分識別的結果超出範圍,且執行記憶體回收,您可能會得到新的實體執行個體。If a previous result with the same identity goes out of scope, and garbage collection runs, you may get a new entity instance.

查詢執行時When queries are executed

當您呼叫 LINQ 運算子時,只是單純在建置查詢的記憶體內表示方式。When you call LINQ operators, you are simply building up an in-memory representation of the query. 只有在取用結果時,才會將查詢傳送到資料庫。The query is only sent to the database when the results are consumed.

以下是導致將查詢傳送到資料庫的最常見作業:The most common operations that result in the query being sent to the database are:

  • for 迴圈中逐一查看結果Iterating the results in a for loop
  • 使用 ToListToArraySingleCount 之類的運算子Using an operator such as ToList, ToArray, Single, Count
  • 將查詢的結果資料繫結到 UIDatabinding the results of a query to a UI

警告

一律驗證使用者輸入: 雖然 EF Core 使用參數以及在查詢中逸出常值來防止 SQL 插入式攻擊,但是它不會驗證輸入。Always validate user input: While EF Core protects against SQL injection attacks by using parameters and escaping literals in queries, it does not validate inputs. 在將不受信任來源的值用於 LINQ 查詢中、指派給實體屬性或傳遞至其他 EF Core API 之前,應該執行針對每個應用程式需求的適當驗證。Appropriate validation, per the application's requirements, should be performed before values from untrusted sources are used in LINQ queries, assigned to entity properties, or passed to other EF Core APIs. 這包括用來以動態方式建構查詢的任何使用者輸入。This includes any user input used to dynamically construct queries. 即使在使用 LINQ 時,如果您接受使用者輸入來建置運算式,就必須確定只會建構預期的運算式。Even when using LINQ, if you are accepting user input to build expressions, you need to make sure that only intended expressions can be constructed.