Entity Framework Core (EF Core) is a powerful Object-Relational Mapper (ORM) for .NET that allows developers to interact with databases using .NET objects. One of EF Core’s most important and powerful features is LINQ (Language Integrated Query) — a feature that allows you to write queries directly in C# using intuitive syntax.
Whether you're working on a Web API, MVC application, or a console app, LINQ in EF Core makes data querying clean, efficient, and maintainable.
What is LINQ?
LINQ (Language Integrated Query) allows you to query collections (like arrays, lists, and database sets) using C# syntax. With EF Core, LINQ becomes the primary way to interact with your database.
Instead of writing raw SQL queries, you use C# expressions to retrieve, filter, and project data from the database.
Benefits of Using LINQ in EF Core
- Type-safe queries
- IntelliSense support in IDEs
- Compile-time checking
- Improved maintainability
- No need for raw SQL
Types of LINQ Queries
var products = await _context.Products .Where(p => p.Price > 100) .OrderBy(p => p.Name) .ToListAsync();
var products = await (from p in _context.Products where p.Price > 100 orderby p.Name select p).ToListAsync();
Common LINQ Query Examples in EF Core.
var products = await _context.Products.ToListAsync();
var expensive = await _context.Products .Where(p => p.Price > 500) .ToListAsync();
var names = await _context.Products .Select(p => p.Name) .ToListAsync();
var sorted = await _context.Products .OrderByDescending(p => p.Price) .ToListAsync();
var product = await _context.Products .FirstOrDefaultAsync(p => p.Id == 1);
bool exists = await _context.Products.AnyAsync(p => p.Price > 1000);
int count = await _context.Products.CountAsync();
var orders = await (from o in _context.Orders join c in _context.Customers on o.CustomerId equals c.Id select new { o.Id, c.Name }).ToListAsync();
Asynchronous Queries in LINQ
- ToListAsync()
- FirstOrDefaultAsync()
- AnyAsync()
- CountAsync()
Performance Tips for LINQ.
- Use `AsNoTracking()` for read-only: Improves performance, skips tracking overhead
- Use `Select()` to limit columns: Reduces DB load and memory usage
- Avoid multiple `.ToListAsync()`: Combine filters before executing the query
- Use `AnyAsync()` instead of `Count()`: Faster existence check
Why Use .Include()?
var products = await _context.Products .Include(p => p.Category) .ToListAsync(); foreach (var product in products) { Console.WriteLine($"Product: {product.Name}, Category: {product.Category.Name}"); }
var products = await _context.Products .Include(p => p.Category) .ThenInclude(c => c.Supplier) .ToListAsync();
- Forget to use await with async methods: Leads to unexecuted queries or runtime bugs.
- Loading too much data: Avoid pulling unnecessary columns or rows.
- N+1 queries: Use .Include() to load related data when needed.
What is Pagination?
Key Parameters in Pagination
- PageNumber: The current page number (e.g., 1, 2, 3…)
- PageSize: Number of records to show per page (e.g., 10, 20)
- Skip: Number of records to skip: (PageNumber - 1) * PageSize
- Take: Number of records to fetch: PageSize
[HttpGet] public async Task<IActionResult> GetPagedProducts(int pageNumber = 1, int pageSize = 10) { var totalCount = await _context.Products.CountAsync(); var products = await _context.Products .OrderBy(p => p.Id) .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); var result = new { TotalCount = totalCount, PageSize = pageSize, CurrentPage = pageNumber, TotalPages = (int)Math.Ceiling((double)totalCount / pageSize), Data = products }; return Ok(result); }
No comments:
Post a Comment