Seniorسختی 4 از ۵· در 64٪ مصاحبههای این حوزه پرسیده شده
مشکل N+1 Query چیست و در EF Core چطور آن را حل میکنید؟
☆نشان کردنپاسخ کوتاه
وقتی برای هر ردیف از یک لیست، یک کوئری جداگانه برای بارگذاری داده مرتبط اجرا میشود؛ راهحل اصلی `Include` یا پروجکشن با `Select` است.
پاسخ کامل
اگر ۱۰۰ سفارش بخوانید و سپس در حلقه به order.Customer.Name دسترسی پیدا کنید،
EF Core با Lazy Loading برای هر سفارش یک کوئری جدا میزند: ۱ کوئری اصلی + ۱۰۰ کوئری
اضافه.
سه راهحل، بهترتیب اولویت:
- پروجکشن (
Select) — فقط ستونهای لازم خوانده میشوند؛ بهترین گزینه برای خواندن. Include/ThenInclude— یک JOIN میزند و همه چیز را یکجا میآورد.AsSplitQuery— وقتیIncludeباعث انفجار کارتزین میشود، آن را به چند کوئری میشکند.
بهترین راه تشخیص، لاگکردن SQL تولیدشده است.
مثال کد
// ❌ N+1
var orders = await context.Orders.ToListAsync();
foreach (var order in orders)
Console.WriteLine(order.Customer.Name);
// ✅ پروجکشن
var rows = await context.Orders
.Select(o => new { o.Id, CustomerName = o.Customer.Name })
.ToListAsync();
نکته مهم
در EF Core، Lazy Loading بهصورت پیشفرض غیرفعال است؛ اگر آن را فعال کردهاید، احتمال N+1 بهشدت بالا میرود.
اشتباه رایج
❌ استفاده از Include برای چند مجموعه همزمان بدون AsSplitQuery — تعداد ردیفهای برگشتی ضرب میشود و کوئری کند میشود.
شرکتهایی که این سؤال را پرسیدهاند
اسنپدیجیکالا
