• 客户端 VS 服务端评估
    • 客户端评估
    • 禁用客户端评估

    客户端 VS 服务端评估

    Entity Framework Core 支持在客户端评估查询的一部分,同时也将其一部分推送给服务端(数据库)评估。数据库提供程序会决定查询的哪些部分交由数据库评估。

    提示

    你可以在 GitHub 上查阅当前文章涉及的代码样例。

    客户端评估

    接下来的代码样例使用了一个帮助器方法来为从SQL Server 数据库返回的 blog 标准化 URL。因为 SQL Server 提供程序不了解该方法的具体实现,不可能将其翻译为 SQL。查询的其他方面都会在数据库服务器上进行评估,而返回并通过该方法传递的 URL 则在客户端进行评估。

    1. var blogs = context.Blogs
    2. .OrderByDescending(blog => blog.Rating)
    3. .Select(blog => new
    4. {
    5. Id = blog.BlogId,
    6. Url = StandardizeUrl(blog.Url)
    7. })
    8. .ToList();
    1. public static string StandardizeUrl(string url)
    2. {
    3. url = url.ToLower();
    4. if (!url.StartsWith("http://"))
    5. {
    6. url = string.Concat("http://", url);
    7. }
    8. return url;
    9. }

    禁用客户端评估

    尽管客户端评估的用处很大,但在一些实例中它可能导致很差的性能。考虑一下下面的查询,帮助器方法被用在了过滤器上。由于方法无法在数据库上执行,所有数据都将被拉取到内存中,然后在客户端应用过滤。基于总数据量,还有被过滤排除的数据量,就可能导致非常严重的性能问题。

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

    默认情况下,EF Core 会在执行客户端评估时输出警告。查看 日志记录 以了解查看日志输出的更多信息。你可以更改这个行为以在发生客户端评估时抛出异常或做其他事情。这可以在装配上下文实例的选项时完成 - 通常在 DbContext.OnConfiguring 或者 Startup.cs里面(如果你使用的是 ASP.NET Core)。

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