- 查询的原理
- 查询的生命周期
- 查询时执行
查询的原理
Entity Framework Core 使用语言集成查询(Language Integrate Query,LINQ)来从数据库中查询数据。LINQ 允许你使用 C#(或者你选择的其他 .NET 语言,比如 VB.NET)来基于你的派生上下文和实体类型编写强类型查询。
查询的生命周期
以下是对每个查询过程的高级概述。
LINQ 查询通过 Entity Framework Core 处理以构建即将传递给数据库提供程序的表示。
- 处理结果会被缓存,这样的话就不用在每次查询时都进行处理
上述处理结果会被传递给数据库提供程序
- 数据库提供程序识别查询的哪些部分可以在数据库中评估
- 识别到的查询的这些部分会被翻译为数据库特定的查询语言(例如,关系数据库的 SQL)
- 一个或多个查询被发送到数据库,然后返回结果集(结果来自数据库,不是实体实例)
对于结果集中的每个项
- 如果这是跟踪查询,EF 会验证数据是否表示上下文实例的变更跟踪器中的实体
- 如果是,则返回已有的实体
- 如果不是,则创建一个新实体,设置变更跟踪,然后返回这个新的实体。
- 如果这是不跟踪查询,EF 会验证数据是否表示当前查询的结果集中的其他实体
- 如果是,则返回已有的实体[1]
- 如果不是,则创建和返回新实体
- 如果这是跟踪查询,EF 会验证数据是否表示上下文实例的变更跟踪器中的实体
[1] 无跟踪查询使用弱引用来保持跟踪已返回的实体实例。如果具有相同标识的之前的结果超出作用范围,则 GC 会执行回收,你可能会获得一个新的实体实例。
查询时执行
在你调用 LINQ 操作的时候,你只是简单地在内存中构建了查询的表示。查询只会在使用结果的时候被发送到数据库。
触发查询被发送到数据库的最通用操作包括:
- 在
for
循环中对结果集进行迭代 - 使用类似于
ToList
、ToArray
、Single
、Count
等的操作 - 将查询结果绑定到 UI
警告
务必要验证用户输入: 尽管 EF 提供了 SQL 注入攻击防护,它并不做任何常规的输入验证。另外,如果传值给 API 、使用 LINQ 查询、给实体属性赋值等等来自不可信的源,那么就应该针对你的每个应用程序需求进行合适的验证。这包括用户用于动态构造查询的任何输入。即便是使用 LINQ,如果你接受用户输入来构建表达式,就需要确保只能构造预期的表达式。