EFCore基础教程
查询数据
Entity Framework Core 使用语言集成查询 (LINQ) 来查询数据库中的数据。 通过 LINQ 可使用 C#(或你选择的其他 .NET 语言)基于派生上下文和实体类编写强类型查询。 LINQ 查询的一种表示形式会传递给数据库提供程序,进而转换为特定于数据库的查询语言(例如,适用于关系数据库的 SQL)。
查询的生命周期
下面是每个查询所经历的过程的高级概述。
- LINQ 查询由 Entity Framework Core 处理,用于生成已准备好由数据库提供程序处理的表示形式
- 结果会被缓存,以便每次执行查询时无需重复进行此处理
- 结果会传递到数据库提供程序
- 数据库提供程序会识别出查询的哪些部分可以在数据库中求值
- 查询的这些部分会转换为特定数据库的查询语言(例如,关系数据库的 SQL)
- 一个或多个查询会发送到数据库并返回结果集(返回的是数据库中的值,而不是实体实例中的)
- 对于结果集中的每一项
- 如果这是跟踪查询,EF 会检查数据是否表示上下文实例内更改跟踪器中的现有实体
- 如果是,则会返回现有实体
- 如果不是,则会创建新实体、设置更改跟踪并返回该新实体
- 如果这是非跟踪查询,EF 会检查数据是否表示此查询结果集中的现有实体
- 如果是,则会返回现有实体 (1)
- 如果不是,则会创建新实体并返回该新实体
- 如果这是跟踪查询,EF 会检查数据是否表示上下文实例内更改跟踪器中的现有实体
(1) 非跟踪查询使用弱引用跟踪已返回的实体。 如果具有相同标识的上一个结果超出范围,并遇到垃圾回收机制执行,则可能会获得新的实体实例。
跟踪与非跟踪查询
跟踪查询
跟踪行为可控制 Entity Framework Core 是否将有关实体实例的信息保留在其更改跟踪器中。 如果已跟踪某个实体,则该实体中检测到的任何更改都会在 SaveChanges()
期间永久保存到数据库。 Entity Framework Core 还会修正从跟踪查询中获取的实体与先前已加载到 DbContext 实例中的实体两者之间的导航属性。
默认情况下,跟踪返回实体类型的查询。 这表示可以更改这些实体实例,然后通过 SaveChanges()
持久化这些更改。
在以下示例中,将检测到对博客评分所做的更改,并在 SaveChanges()
期间将这些更改持久化到数据库中。
using (var context = new BloggingContext()) { var blog = context.Blogs.SingleOrDefault(b => b.BlogId == 1); blog.Rating = 5; context.SaveChanges(); }
非跟踪查询
在只读方案中使用结果时,非跟踪查询十分有用。 可以更快速地执行非跟踪查询,因为无需设置更改跟踪信息。
可以交换单个非跟踪查询:
using (var context = new BloggingContext()) { var blogs = context.Blogs .AsNoTracking() .ToList(); }
还可以在上下文实例级别更改默认跟踪行为:
using (var context = new BloggingContext()) { context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var blogs = context.Blogs.ToList(); }
跟踪和投影
即使查询的结果类型不是实体类型,但如果结果包含实体类型,则默认情况下也会跟踪这些实体类型。 在以下返回匿名类型的查询中,会跟踪结果集中 Blog
的实例。
using (var context = new BloggingContext()) { var blog = context.Blogs .Select(b => new { Blog = b, Posts = b.Posts.Count() }); }
如果结果集不包含任何实体类型,则不会执行跟踪。 在以下返回匿名类型(具有实体中的某些值,但没有实际实体类型的实例)的查询中,不会执行跟踪。
using (var context = new BloggingContext()) { var blog = context.Blogs .Select(b => new { Id = b.BlogId, Url = b.Url }); }
执行查询时
调用 LINQ 运算符时,只会构建查询在内存中的表示形式。 只有在使用结果时,查询才会发送到数据库。
导致查询发送到数据库的最常见操作如下:
- 在
for
循环中循环访问结果 - 使用
ToList
、ToArray
、Single
、Count
等操作 - 将查询结果数据绑定到 UI