Category: EF Core

  • ASP.NET Core Filters: Stop Repeating the Same Code in Every Controller

    ASP.NET Core Filters: Stop Repeating the Same Code in Every Controller

    When I first started building ASP.NET Core APIs, I noticed a pattern.

    Many controller actions contained the same code:

    • Validate requests.
    • Check permissions.
    • Log execution time.
    • Handle exceptions.
    • Write audit logs.

    The APIs worked.

    But every new endpoint meant copying the same logic again.

    That’s when I discovered Filters.

    I realized they weren’t just another ASP.NET Core feature—they were a way to keep controllers focused on business logic while moving cross-cutting concerns to reusable components.

    What Are Filters?

    Filters allow you to execute code before or after an action method runs.

    Instead of repeating common logic in every controller, you write it once and apply it wherever it’s needed.


    Types of Filters

    Authorization Filter

    Runs first and determines whether the request is authorized.

    Example:

    • Check user permissions.
    • Validate custom authorization rules.

    Resource Filter

    Executes before model binding.

    Useful for:

    • Caching
    • Short-circuiting requests
    • Resource initialization

    Action Filter

    Runs before and after the controller action.

    Common use cases:

    • Input validation
    • Logging
    • Measuring execution time
    • Auditing

    Exception Filter

    Handles exceptions thrown by controller actions.

    Useful for:

    • Logging exceptions
    • Returning consistent error responses

    Result Filter

    Runs before and after the action result is executed.

    Useful for:

    • Modifying response headers
    • Wrapping API responses
    • Adding metadata

    When Should You Use Filters?

    Filters are ideal for logic that applies across multiple endpoints.

    Examples include:

    • Audit logging
    • Request validation
    • Performance monitoring
    • Response formatting
    • Custom authorization

    If you find yourself copying the same code into multiple controllers, it’s often a sign that a filter could help.


    When Should You Avoid Filters?

    Filters aren’t the answer for every problem.

    Choose the right tool for the job:

    • Middleware for application-wide concerns such as authentication, CORS, or request logging.
    • Filters for MVC or API action-specific behavior.
    • Services for business logic.

    Keeping these responsibilities separate leads to a cleaner architecture.


    Final Thoughts

    One lesson changed the way I structure APIs:

    Controllers should coordinate requests—not perform every supporting task themselves.

    Filters help eliminate duplication, improve maintainability, and keep your business logic where it belongs.

  • Change Tracking in EF Core: What It Is and When Should You Use It?

    Change Tracking in EF Core: What It Is and When Should You Use It?

    One of the most powerful features of Entity Framework Core is Change Tracking.

    It allows EF Core to automatically detect changes made to entities and persist them to the database.

    But while it’s incredibly useful, it’s not always necessary.

    Understanding when to use Change Tracking—and when to disable it—can significantly improve your application’s performance.


    What Is Change Tracking?

    When EF Core retrieves an entity, it keeps track of its original state.

    If you modify one of its properties, EF Core detects the change.

    When you call SaveChanges(), only the modified values are sent to the database.

    Example:

    var product = await context.Products
        .FirstAsync(p => p.Id == 1);
    
    product.Price = 1200;
    
    await context.SaveChangesAsync();
    

    Notice that we never call Update().

    EF Core already knows that Price changed.


    How Does It Work?

    When an entity is loaded:

    • EF Core stores the original values.
    • It monitors property changes.
    • During SaveChanges(), it compares the current values with the original values.
    • Only the necessary SQL UPDATE statement is generated.

    This makes updates simple and reduces boilerplate code.


    When Should You Use Change Tracking?

    Change Tracking is ideal when:

    • Updating existing records.
    • Inserting related entities.
    • Managing relationships.
    • Performing CRUD operations where data will be modified.

    When Should You Avoid It?

    If you’re only reading data, Change Tracking adds unnecessary overhead.

    In those cases, use:

    var products = await context.Products
        .AsNoTracking()
        .ToListAsync();
    

    This avoids tracking every entity and can improve performance, especially for large result sets.


    Change Tracking vs AsNoTracking()

    With Change Tracking

    var product = await context.Products
        .FirstAsync();
    
    product.Price = 1200;
    
    await context.SaveChangesAsync();
    

    ✅ Changes are automatically detected and saved.


    With AsNoTracking()

    var product = await context.Products
        .AsNoTracking()
        .FirstAsync();
    

    The entity is not tracked.

    If you modify it and call SaveChanges(), nothing happens unless you explicitly attach or update the entity.


    Performance Considerations

    Tracking every entity consumes:

    • Memory
    • CPU
    • Change detection time

    For read-heavy APIs or reporting queries, disabling tracking can provide noticeable performance improvements.

    However, don’t disable tracking if you intend to modify the entities afterwards.


    Best Practices

    ✅ Use Change Tracking for create, update, and delete operations.

    ✅ Use AsNoTracking() for read-only queries.

    ✅ Avoid tracking thousands of entities unnecessarily.

    ✅ Understand whether your query needs tracked or untracked entities before optimizing.


    Final Thoughts

    Change Tracking is one of the reasons EF Core makes data updates so convenient.

    But like any feature, it should be used intentionally.

    A simple rule I follow is:

    • Reading data? → Use AsNoTracking().
    • Updating data? → Let EF Core track the entity.

    Choosing the right approach helps you build applications that are both clean and efficient.