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

      

  • 相关阅读:
    Google Map API基本概念(转载)很好的例子
    Sql Exception Handling & Throw Exception
    幸福人生讲座(十):五伦中哪一伦最重要?
    Delete Database Log
    杨澜语录
    余世雄 如何提升职场“执行力”
    红楼女梦
    假如我真的看透了
    余世维 有效沟通
    习惯修养
  • 原文地址:https://www.cnblogs.com/lbonet/p/14599495.html
Copyright © 2020-2023  润新知