LINQ نوشتن کوئری‌ها را خوانا و یکپارچه می‌کند، اما در پروژه‌های واقعی صرفاً استفاده از Where و Select کافی نیست. این مقاله با تمرکز بر کارایی و قابلیت نگهداری نشان می‌دهد چگونه فیلترهای داینامیک و Projectionهای دقیق بنویسیم تا هزینه پایگاه‌داده و حافظه کاهش یابد.

۱) فیلترهای پیشرفته و داینامیک

نمونه کد برای فیلترهای اختیاری:

var query = db.Users.AsQueryable();

if (!string.IsNullOrWhiteSpace(searchName))
    query = query.Where(u => u.Name.Contains(searchName));

if (minAge.HasValue)
    query = query.Where(u => u.Age >= minAge.Value);

if (maxAge.HasValue)
    query = query.Where(u => u.Age <= maxAge.Value);

var users = await query
    .OrderBy(u => u.Id)
    .Skip((page - 1) * pageSize)
    .Take(pageSize)
    .ToListAsync();

۲) Projectionهای کارا

فقط داده‌های لازم را واکشی کنید:

var users = await db.Users
    .Select(u => new { u.Id, u.Name })
    .ToListAsync();

Projection به DTO:

public class UserDto
{
    public string Name { get; set; }
    public int OrderCount { get; set; }
}

var users = await db.Users
    .Select(u => new UserDto
    {
        Name = u.Name,
        OrderCount = u.Orders.Count()
    })
    .ToListAsync();

۳) Grouping و Aggregation

var report = await db.Orders
    .GroupBy(o => o.CustomerId)
    .Select(g => new
    {
        CustomerId = g.Key,
        TotalOrders = g.Count(),
        TotalAmount = g.Sum(o => o.Total)
    })
    .ToListAsync();

۴) نکات بهینه‌سازی EF Core

  • استفاده از AsNoTracking() برای کوئری‌های فقط-خواندنی.
  • انتخاب فقط ستون‌های لازم با Projection.
  • جلوگیری از N+1 Problem با Select شکل‌داده.
  • استفاده از AsSplitQuery() در روابط چندگانه.
  • کامپایل کردن کوئری‌های پرتکرار با EF.CompileQuery.

جمع‌بندی

با فیلترهای داینامیک، Projectionهای دقیق، Grouping و نکات EF Core می‌توان کوئری‌هایی نوشت که هم سریع اجرا شوند و هم نگهداری ساده‌ای داشته باشند. این مهارت‌ها برای پروژه‌های واقعی ضروری هستند.