有没有办法强制Entity Framwork使用子查询的别名而不是为OrderBy加倍?
var results = Users.Select( u => new { u.idUser,u.Name,nbChilds = u.Children.Count }) .OrderBy( u => u.nbChilds );
这将在sql中转换为:
SELECT [u].[idUser] AS [idUser],[u].[name] AS [Name],( SELECT COUNT(*) FROM [Children] AS [c0] ) AS [nbChilds] FROM [Users] AS [u] ORDER BY ( SELECT COUNT(*) FROM [Children] AS [c] )
这意味着它将运行两次子计数.在我的情况下,这是一个严重的性能打击,我想避免.有没有办法告诉Linq在select中使用别名,所以输出将是:
SELECT [u].[idUser] AS [idUser],( SELECT COUNT(*) FROM [Children] AS [c0] ) AS [nbChilds] FROM [Users] AS [u] ORDER BY [nbChilds]
解决方法
EF6在生成此查询方面做得很好. EF Core重复ORDER BY中的子查询,对于sql Server至少会导致更昂贵的计划.
sql生成仍然是EF Core的一个活跃的改进领域.请为此针对EF Core提出问题:https://github.com/aspnet/EntityFrameworkCore/issues
var q = from b in db.Blogs orderby b.Posts.Count select new { b.Name,NumPosts = b.Posts.Count }; var l = q.ToList();
翻译成这样:
SELECT [Project2].[Id] AS [Id],[Project2].[Name] AS [Name],[Project2].[C2] AS [C1] FROM ( SELECT [Project1].[Id] AS [Id],[Project1].[Name] AS [Name],[Project1].[C1] AS [C1],(SELECT COUNT(1) AS [A1] FROM [dbo].[Posts] AS [Extent3] WHERE [Project1].[Id] = [Extent3].[BlogId]) AS [C2] FROM ( SELECT [Extent1].[Id] AS [Id],[Extent1].[Name] AS [Name],(SELECT COUNT(1) AS [A1] FROM [dbo].[Posts] AS [Extent2] WHERE [Extent1].[Id] = [Extent2].[BlogId]) AS [C1] FROM [dbo].[Blogs] AS [Extent1] ) AS [Project1] ) AS [Project2] ORDER BY [Project2].[C1] ASC
但是在EF Core上,子查询在ORDER BY子句中重复:
这是一个复制品
using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Data; using System.Data.sqlClient; using System.Linq; using System.Threading.Tasks; namespace EfCoreTest { public class Category { public int CategoryId { get; set; } public virtual ICollection<Product> Products { get; } = new HashSet<Product>(); } public class Product { public int ProductId{ get; set; } public string Name { get; set; } public DateTime Date { get; set; } public Category Category { get; set; } } public class Db : DbContext { public DbSet<Category> Categorys { get; set; } public DbSet<Product> Products { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UsesqlServer("server=.;database=EfCoreTest;Integrated Security=true"); base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } } class Program { static void Main(string[] args) { using (var db = new Db()) { db.Database.EnsureDeleted(); db.Database.EnsureCreated(); for (int i = 0; i < 100; i++) { var t = new Category(); for (int j = 0; j < 1000; j++) { var product = new Product() { Category = t,Date = DateTime.Now,Name = $"Category {j}{i}" }; db.Add(product); } db.Add(t); } db.SaveChanges(); } using (var db = new Db()) { var q = from c in db.Categorys orderby c.Products.Count select new { c.CategoryId,ProductCount = c.Products.Count }; var l = q.ToList(); Console.WriteLine("Hit any key to exit."); Console.ReadKey(); } } } }
SELECT [c].[CategoryId],( SELECT COUNT(*) FROM [Products] AS [p0] WHERE [c].[CategoryId] = [p0].[CategoryId] ) AS [ProductCount] FROM [Categorys] AS [c] ORDER BY ( SELECT COUNT(*) FROM [Products] AS [p] WHERE [c].[CategoryId] = [p].[CategoryId] )
(100 rows affected) Table 'Worktable'. Scan count 0,logical reads 0,physical reads 0,read-ahead reads 0,lob logical reads 0,lob physical reads 0,lob read-ahead reads 0. Table 'Categorys'. Scan count 1,logical reads 2,lob read-ahead reads 0. Table 'Products'. Scan count 2,logical reads 960,lob read-ahead reads 0. sql Server Execution Times: cpu time = 31 ms,elapsed time = 43 ms.
SELECT [c].[CategoryId],( SELECT COUNT(*) FROM [Products] AS [p0] WHERE [c].[CategoryId] = [p0].[CategoryId] ) AS [ProductCount] FROM [Categorys] AS [c] ORDER BY ( [ProductCount] )
以及时间和IO统计数据:
(100 rows affected) Table 'Worktable'. Scan count 0,lob read-ahead reads 0. Table 'Products'. Scan count 1,logical reads 480,lob read-ahead reads 0. sql Server Execution Times: cpu time = 15 ms,elapsed time = 20 ms.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。