DEV Community

mohamed Tayel
mohamed Tayel

Posted on • Edited on

EFCore Tutorial P8:Filtering, Sorting, and Paging

Meta Description: Learn how to efficiently implement filtering, sorting, and paging in a console application using Entity Framework Core (EF Core). This step-by-step guide uses a simple e-commerce example to show you how to manage large datasets and improve application performance.

Introduction

In any application that deals with data, it is crucial to implement efficient filtering, sorting, and paging mechanisms to present manageable and relevant data to users. In this article, we’ll focus on implementing these features in a console application using Entity Framework Core (EF Core).

We will use a simple e-commerce example, where we query products, orders, and inventory. This example will show how to return only the products that meet specific criteria, how to order them, and how to paginate the results for optimal performance and user experience.

Where to Write These Methods

In your console application, you should place these methods inside the relevant service classes you’ve already set up, such as ProductService, OrderService, or InventoryService.

For each section below, I will indicate where each method should be placed:

  1. ProductService: Handles all product-related operations, such as filtering, sorting, and paging products.
  2. OrderService: Handles queries related to orders.
  3. InventoryService: Manages inventory-related queries.

These services should interact with the AppDbContext to access the database and retrieve the relevant data.

1. Filtering in EF Core

Method Location: ProductService

Filtering allows you to retrieve only the relevant records from the database. In EF Core, you can use LINQ queries with Where() to filter data based on conditions.

Here’s how you can filter products by category in the ProductService:

public List<Product> GetProductsByCategory(string categoryName)
{
    return _context.Products
                   .Where(p => p.Category.Name == categoryName)
                   .Include(p => p.Inventory)  // Eagerly loading Inventory data
                   .ToList();
}
Enter fullscreen mode Exit fullscreen mode

In this example, we are filtering the products to show only those that belong to a specified category. The Where clause helps narrow down the results based on the category name.

Usage Example (Inside your Program.cs):

var productService = new ProductService(new AppDbContext());
var electronicsProducts = productService.GetProductsByCategory("Electronics");
foreach (var product in electronicsProducts)
{
    Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
}
Enter fullscreen mode Exit fullscreen mode

2. Sorting in EF Core

Method Location: ProductService

Sorting allows you to arrange data in a specific order, such as by price or name. In EF Core, this can be done using the OrderBy() and OrderByDescending() methods.

Here’s how you can sort products by price in ascending order:

public List<Product> GetProductsSortedByPrice()
{
    return _context.Products
                   .OrderBy(p => p.Price)
                   .ToList();
}
Enter fullscreen mode Exit fullscreen mode

To sort in descending order:

public List<Product> GetProductsSortedByPriceDescending()
{
    return _context.Products
                   .OrderByDescending(p => p.Price)
                   .ToList();
}
Enter fullscreen mode Exit fullscreen mode

Usage Example:

var sortedProducts = productService.GetProductsSortedByPrice();
foreach (var product in sortedProducts)
{
    Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
}
Enter fullscreen mode Exit fullscreen mode

3. Paging in EF Core

Method Location: ProductService

Paging is essential when handling large datasets. Instead of retrieving all records at once, you can fetch a subset of records, making the query more efficient and user-friendly.

In EF Core, paging is implemented using Skip() and Take() methods. Here's how you can retrieve a paged list of products:

public List<Product> GetPagedProducts(int pageNumber, int pageSize)
{
    return _context.Products
                   .OrderBy(p => p.Name)  // Ensure consistent ordering
                   .Skip((pageNumber - 1) * pageSize)
                   .Take(pageSize)
                   .ToList();
}
Enter fullscreen mode Exit fullscreen mode

In this example, Skip() is used to skip records from the previous pages, and Take() limits the results to the page size.

Usage Example:

var pagedProducts = productService.GetPagedProducts(2, 10);  // Get page 2 with 10 products
foreach (var product in pagedProducts)
{
    Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
}
Enter fullscreen mode Exit fullscreen mode

4. Combining Filtering, Sorting, and Paging

Often, you’ll want to combine filtering, sorting, and paging in a single query. Here’s an example that combines all three:

Method Location: ProductService

public List<Product> GetFilteredSortedPagedProducts(string categoryName, int pageNumber, int pageSize)
{
    return _context.Products
                   .Where(p => p.Category.Name == categoryName)  // Filter by category
                   .OrderBy(p => p.Price)  // Sort by price
                   .Skip((pageNumber - 1) * pageSize)  // Apply paging
                   .Take(pageSize)
                   .ToList();
}
Enter fullscreen mode Exit fullscreen mode

Usage Example:

class Program
{
    static async Task Main(string[] args)
    {
        //CallProdcut();
        //CallInventory();
        //callOrder();
        // await TestQueryPerformanceAsync();

        // Call the new methods for filtering, sorting, and paging
        CallFilteredProducts();
        CallSortedProducts();
        CallPagedProducts();
    }

    private static void CallFilteredProducts()
    {
        using (var context = new AppDbContext())
        {
            var productService = new ProductService(context);

            // Retrieve filtered products by category
            var filteredProducts = productService.GetProductsByCategory("Electronics");
            Console.WriteLine("Filtered Products by Category 'Electronics':");
            foreach (var product in filteredProducts)
            {
                Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
            }
        }
    }

    private static void CallSortedProducts()
    {
        using (var context = new AppDbContext())
        {
            var productService = new ProductService(context);

            // Retrieve sorted products by price (ascending)
            var sortedProducts = productService.GetProductsSortedByPrice();
            Console.WriteLine("Sorted Products by Price (Ascending):");
            foreach (var product in sortedProducts)
            {
                Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
            }
        }
    }

    private static void CallPagedProducts()
    {
        using (var context = new AppDbContext())
        {
            var productService = new ProductService(context);

            // Retrieve paged products (page 1, 10 items per page)
            var pagedProducts = productService.GetPagedProducts(1, 10);
            Console.WriteLine("Paged Products (Page 1, 10 products per page):");
            foreach (var product in pagedProducts)
            {
                Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

How It Works:

  1. CallFilteredProducts():

    • Retrieves and prints products filtered by the category "Electronics".
  2. CallSortedProducts():

    • Retrieves and prints products sorted by price in ascending order.
  3. CallPagedProducts():

    • Retrieves and prints the first page of products, with 10 products per page.

Each method is called from Main(), and they interact with the ProductService to perform filtering, sorting, and paging.

Conclusion

By implementing filtering, sorting, and paging in your console application using EF Core, you can greatly improve the performance and scalability of your data access layer. With these techniques, you can handle large datasets more effectively and present users with relevant, manageable information.

These methods can be added to your existing service classes, such as ProductService, to ensure your application is organized and follows good practices.


Let me know if you'd like to modify or add anything to this draft!

Top comments (0)