EFCore基础教程

查询数据

  Entity Framework Core 使用语言集成查询 (LINQ) 来查询数据库中的数据。 通过 LINQ 可使用 C#(或你选择的其他 .NET 语言)基于派生上下文和实体类编写强类型查询。 LINQ 查询的一种表示形式会传递给数据库提供程序,进而转换为特定于数据库的查询语言(例如,适用于关系数据库的 SQL)。

查询的生命周期

下面是每个查询所经历的过程的高级概述。

  1. LINQ 查询由 Entity Framework Core 处理,用于生成已准备好由数据库提供程序处理的表示形式
    1. 结果会被缓存,以便每次执行查询时无需重复进行此处理
  2. 结果会传递到数据库提供程序
    1. 数据库提供程序会识别出查询的哪些部分可以在数据库中求值
    2. 查询的这些部分会转换为特定数据库的查询语言(例如,关系数据库的 SQL)
    3. 一个或多个查询会发送到数据库并返回结果集(返回的是数据库中的值,而不是实体实例中的)
  3. 对于结果集中的每一项
    1. 如果这是跟踪查询,EF 会检查数据是否表示上下文实例内更改跟踪器中的现有实体
      • 如果是,则会返回现有实体
      • 如果不是,则会创建新实体、设置更改跟踪并返回该新实体
    2. 如果这是非跟踪查询,EF 会检查数据是否表示此查询结果集中的现有实体
      • 如果是,则会返回现有实体 (1)
      • 如果不是,则会创建新实体并返回该新实体

(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 循环中循环访问结果
  • 使用 ToListToArraySingleCount 等操作
  • 将查询结果数据绑定到 UI
posted @ 2019-06-10 21:13  l1honghui  阅读(5991)  评论(1编辑  收藏  举报