ฉันมีเอนทิตี Post
ที่มีความสัมพันธ์แบบหนึ่งต่อกลุ่มกับ Author
และ Comment
ฉันต้องการโหลด Post
s ทั้งหมดและรวมเข้ากับ Author
แรกและ Comment
s ทั้งหมด รหัสที่มี Include
จะมีลักษณะดังนี้:
Post[] posts = ctx.Posts.Include(p => p.Authors.Take(1)).Include(p => p.Comments).ToArray();
มีปัญหาการระเบิดแบบคาร์ทีเซียนกับแบบสอบถามนี้ ถ้า Post
เป็นเจ้าของ n
Comments
, Author
และ Comment
จะถูกทำซ้ำ n
ครั้งในชุดผลลัพธ์
โซลูชัน #1
ใน EF Core 5.0 ฉันสามารถใช้ แยกแบบสอบถาม แต่จากนั้นจะสร้าง 3 แบบสอบถามเมื่อฉันต้องการโหลด Post
ด้วย Author
ก่อน จากนั้นจึงทั้งหมด Comment
s
โซลูชัน # 2
ขั้นแรก โหลด Post
ด้วย Author
จากนั้นวนซ้ำในโพสต์ไปที่ โหลดความคิดเห็นของพวกเขาอย่างชัดเจน แต่นั่นจะสร้างข้อความค้นหา n + 1
รายการ
Post[] posts = ctx.Posts.Include(p => p.Authors.Take(1)).ToArray();
foreach (Post post in posts)
ctx.Entry(post).Collection(p => p.Comments).Load();
โซลูชัน # 3
ขั้นแรก โหลด Post
ด้วย Author
จากนั้นรวบรวมรหัสโพสต์ทั้งหมดเพื่อสร้างแบบสอบถามเดียวเพื่อโหลดความคิดเห็น
Dictionary<int, Post> postsById = ctx.Posts.Include(p => p.Authors.Take(1)).ToDictionnary(p => p.Id);
Comment[] comments = ctx.Comments.Where(c => postsById.ContainsKey(c.PostId)).ToArray();
foreach (Comment comment in comments)
postsById[comment.PostId].Comments.Add(comment); // How to avoid re-adding comment?
โซลูชันนี้จะสร้างเพียง 2 แบบสอบถามโดยไม่มีข้อมูลที่ซ้ำกัน แต่ฉันจะหลีกเลี่ยงการเพิ่มความคิดเห็นในโพสต์อีกครั้งได้อย่างไร มีวิธีที่ดีกว่า 3 วิธีแก้ปัญหาที่เสนอหรือไม่
Include
จะทำให้เกิดชุดผลลัพธ์จำนวนมหาศาลจากการสืบค้น SQL ในที่สุดเมื่อจำนวนบันทึกที่เกี่ยวข้องเพิ่มขึ้น ในที่สุดฉันก็เปลี่ยนมาใช้ ADO สำหรับการสืบค้นประเภทนี้ - ช่วยให้ฉันแยกการสืบค้นด้วยตนเองและเรียกใช้การสืบค้นทั้งหมดพร้อมกัน (เนื่องจาก EF ไม่ปลอดภัยสำหรับเธรด) ประสิทธิภาพที่เพิ่มขึ้นทั้งกลางวันและกลางคืน - person crgolden   schedule 11.12.2020