【EFCORE笔记】客户端与服务端求值&跟踪与非跟踪查询

客户端与服务端求值

 

在下面的示例中,一个辅助方法用于标准化从 SQL Server 数据库中返回的博客的 URL 由于 SQL Server 提供程序不了解此方法的实现方式,因此不可以将其转换为 SQL 除了在客户端上是通过执行该方法来返回 URL,查询的其余部分都是在数据库中执行的。

var blogs = context.Blogs
        .OrderByDescending(blog => blog.Rating)
        .Select(blog => new
        {
                Id = blog.BlogId,
                Url = StandardizeUrl(blog.Url)
        })
        .ToList();

  

public static string StandardizeUrl(string url)
{
        url = url.ToLower();

        if (!url.StartsWith("http://"))
        {
                url = string.Concat("http://", url);
        }

        return url;
}

  

客户端求值性能问题

var blogs = context.Blogs
        .Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
        .ToList();

  

默认情况下,当执行客户端求值时,EF Core 将记录警告,客户端求值引发异常。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
        optionsBuilder
                .UseSqlServer(@"Server=
(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;   ")
                .ConfigureWarnings(warnings => 
warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}

  

跟踪与非跟踪查询

EF Core 中查询数据时EF Core 内置的跟踪器将对查询返回的实体进行跟踪,当修改实体时,会将检测到的任何更改

 

都会在 SaveChanges() 期间永久保存到数据库。

 

EF CORE 跟踪器对一个对象跟踪以下四种状态

Added: 实体在数据库中不存在,调用 SaveChanges 方式时会将实体 Insert 插入到数据库。

Unchanged:实体存在于数据库中,但客户端查询出来后未进行过修改,当调用 SaveChanges 时将忽略。

Updateed:实体存在数据库中,查询出来后进行了修改,当调用 SaveChanges 方法时,将 Update 更新到数据库。

Deleted:实体存在于数据库,单客户端调用了删除方法从内存中移除,用 SaveChanges 方法时,将从数据库中Delete 移除。

 

 

跟踪查询

using (var context = new BloggingContext())
{
        var blog = context.Blogs.SingleOrDefault(b => b.BlogId == 1);
        blog.Rating = 5;
        context.SaveChanges();
}

  

虽然跟踪器非常方便,但当查询数据时,上下文会创建实体的快照,实体从而被跟踪比较变更。跟踪的目的是监控变更,     当提交 SaveChanges时,保存到数据库,但有时候,我们只查询数据,只读数据,不写入,不需要修改数据,这个时

候,我们跟踪器就时多余的了,但跟踪器会占用快照内存和跟踪本身的性能消耗,所以不跟踪最好,可以这样做。

using (var context = new BloggingContext())
{
        var blogs = context.Blogs
                .AsNoTracking()
                .ToList();
}

  

以上针对某次查询中不跟踪设置,还可全局设置查询不跟踪,这样就方便一次查询多张表,不用每个都 AsNoTracking了。

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
                        });
}

  

posted @ 2021-03-30 23:34  LBO.net  阅读(256)  评论(0编辑  收藏  举报
//返回顶部