如何避免EF Core 2.1中的n + 1个查询?

Lie*_*ero 5 c# sql-server entity-framework-core asp.net-core-2.0

我正在使用EF Core 2.1预览本应该减少N + 1查询问题.我正在尝试进行查询,选择论坛帖子与帖子的作者:

dbContext.ForumThreads
   .Include(t => t.Posts)
   .Take(n)
   .Select(t => new
   {
      t.Id,
      t.Title,
      PostAuhtors = t.Posts.Select(p => p.Author).Take(5)
   }).ToArray();
Run Code Online (Sandbox Code Playgroud)

这会生成n + 1个查询:对于每个ForumThread,它会选择帖子作者

架构很简单:

public class ForumThread 
{
   public Guid Id {get;set;}
   public string Title {get;set;}
   public ICollection<ForumPost> Posts {get;set;}
}

public class ForumPost 
{
  public Guid Id {get;set;}
  public string Author {get;set;}
  public string Content {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

小智 1

我认为您可以通过更少的查询(仅 2 个)来实现这一点,从而在内存中实现某些行为。这段代码能达到你想要的效果吗?

\n\n
class Program\n    {\n        static void Main(string[] args)\n        {\n            using (var db = new SampleContext())\n            {\n                Console.ReadLine();\n                var result = db.Threads\n                    .Include(t => t.Posts)\n                    .Take(10)\n                    .Select(t => new\n                    {\n                        t.Id,\n                        t.Title,\n                        t.Posts\n                        // Do this in memory  \n                        //PostAuhtors = t.Posts.Select(p => p.Author).Take(5)\n                    }).ToArray();\n\n                Console.WriteLine($"\xc2\xbb {result.Count()} Threads.");\n                foreach (var thread in result)\n                {\n                    // HERE !!\n                    var PostAuhtors = thread.Posts.Select(p => p.Author).Take(5);\n                    Console.WriteLine($"\xc2\xbb {thread.Title}:  {string.Join("; ", PostAuhtors)} authors");\n                }\n                Console.ReadLine();\n            }\n        }\n    }\n\n    public class SampleContext : DbContext\n    {\n        public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] {\n                new ConsoleLoggerProvider((category, level)\n                    => category == DbLoggerCategory.Database.Command.Name\n                       && level == LogLevel.Debug, true)\n            });\n\n        public DbSet<ForumThread> Threads { get; set; }\n        public DbSet<ForumPost> Posts { get; set; }\n\n        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n        {\n            optionsBuilder  \n                .EnableSensitiveDataLogging()\n                .UseLoggerFactory(MyLoggerFactory)\n                .UseSqlServer(@"Server=(localdb)\\mssqllocaldb;Database=EFStart;Trusted_Connection=True;");\n        }\n    }\n\n    public class ForumThread\n    {\n        public Guid Id { get; set; }\n        public string Title { get; set; }\n        public ICollection<ForumPost> Posts { get; set; }\n    }\n\n    public class ForumPost\n    {\n        public Guid Id { get; set; }\n        public string Author { get; set; }\n        public string Content { get; set; }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是输出:\n在此输入图像描述

\n