Showing posts with label entity framework. Show all posts
Showing posts with label entity framework. Show all posts

Wednesday, 24 December 2025

Building Clean APIs with ASP.NET Core and Entity Framework

API Architecture Banner
Building Clean APIs with ASP.NET Core

Best practices for designing maintainable, scalable, and secure REST APIs

Creating an API that works is easy. Creating an API that is maintainable, testable, and pleasant to consume is an art. In the .NET ecosystem, ASP.NET Core combined with Entity Framework (EF) Core gives us a powerful toolkit, but it's up to us to use it wisely.

This guide covers the essential patterns for building clean, professional-grade APIs, moving beyond simple CRUD to robust enterprise architecture.

1. Separation of Concerns: The Service Layer

One of the most common mistakes is putting business logic directly inside Controllers. This makes code hard to test and reuse. Instead, aim for a clear layered architecture.

Clean Architecture Diagram

The Onion Architecture: Dependencies point inwards.

❌ The Bad Way (Fat Controller)

[HttpPost]
public IActionResult CreateOrder(OrderDto dto) {
    // Validation logic mixed with business logic
    if(dto.Amount < 0) return BadRequest();
    
    var order = new Order { ... };
    _dbContext.Orders.Add(order); // Direct DB access in controller
    _dbContext.SaveChanges();
    return Ok(order);
}

✅ The Clean Way (Service Pattern)

[HttpPost]
public async Task<IActionResult> CreateOrder(OrderDto dto) {
    // Controller only handles HTTP concerns
    var result = await _orderService.CreateOrderAsync(dto);
    return Ok(result);
}

2. Global Error Handling with Middleware

Don't wrap every controller action in a try-catch block. It clutters your code. Instead, use Middleware to catch exceptions globally and return a standardized error response.

Middleware Pipeline

The Request Pipeline: Logic flows through middleware layers.

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(httpContext, ex);
        }
    }

    private Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        return context.Response.WriteAsync(new ErrorDetails()
        {
            StatusCode = context.Response.StatusCode,
            Message = "Internal Server Error from the custom middleware."
        }.ToString());
    }
}

3. Validation with FluentValidation

Data annotations (Attributes) can get messy. FluentValidation allows you to separate validation rules from your models, keeping your DTOs clean.

public class OrderValidator : AbstractValidator<OrderDto> 
{
    public OrderValidator() 
    {
        RuleFor(x => x.ProductName).NotEmpty();
        RuleFor(x => x.Amount).GreaterThan(0).WithMessage("Price must be positive");
    }
}

4. Use DTOs (Data Transfer Objects)

Never expose your database entities directly to the API client. It creates a tight coupling between your database schema and your public interface.

Scenario: You add a `PasswordHash` column to your User table. If you return the Entity directly, you just leaked everyone's password hashes!

Always map your Entites to DTOs. Libraries like AutoMapper or manual mapping work great.

Conclusion

Building clean APIs is about discipline. By separating concerns, implementing global error handling, and using DTOs, you create a codebase that your team will enjoy working on for years to come.

Wednesday, 5 August 2020

Entity Framework Core with Existing Database

Entity Framework Core only supports code first database aproach. 
To use existing database, we'll need to reverse Engineer Model from existing Database. 
  • Open Visual studio.
  • Menu > tools >Nuget Package Manager >
  • open PM Console
Note: All the tables in the database must have Primary key defined. else you'll get error like:
Unable to generate entity type for table 'dbo.xOrdersMBS'.
Unable to identify the primary key for table 'dbo.xActivePricesEPB'.
Unable to generate entity type for table 'dbo.xActivePricesEPB'.
Unable to identify the primary key for table 'dbo.xLeadTimePBOM'.
Unable to generate entity type for table 'dbo.xLeadTimePBOM'.


 In the console, run the below power shell commands:

Using Windows Authentication:
Scaffold-DbContext "Server=DatabaseServerAddress;Database=DatabaseName;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -f

Using SQL Account:
Scaffold-DbContext "data source=DatabaseServerAddress;initial catalog=DatabaseName;uid=UserName;pwd=Password;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -f

Note: -f force create the files if the file exist in the folder Models.

Thursday, 2 July 2020

EntityFramework Insert error due to PrimaryKey



MyProject.Controllers.CurrencyCodesController Unable to update the EntitySet 'CurrencyCodes' because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.
System.Data.Entity.Infrastructure.DbUpdateException: Unable to update the EntitySet 'CurrencyCodes' because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation. ---> System.Data.Entity.Core.UpdateException: Unable to update the EntitySet 'CurrencyCodes' because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.


Scenario: 
The error occured while trying to insert the currencycodes entity to the database. 
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "cucCurrencyCode,cucDescription,cucMultiplier,cucRate,cucInUse")] CurrencyCode currencyCode)
{ if (ModelState.IsValid)
{ try
{ db.CurrencyCodes.Add(currencyCode);
db.SaveChanges();
}
 catch (Exception ex) {
log.Error(ex.Message, ex);
}
 return RedirectToAction("Index");
} return View(currencyCode);

}



Solution: 
1) Check Primary key in .edmx file.  In my case cucInUse was set as Entity key. I removed it.
2) Now Right click the .edmx file and click "Open with...". Select XML (text) Editor
3)  Find the element <EntitySet name = "CurrencyCodes"...>
4) Change store:Schema="dbo" => Schema="dbo"
5) delete element <DefiningQuery>
6) Clean the project. 
7) close Visual studio.
8) Open visual studio. Open the project. 
9) Clean and build the project. 
10) Run the application.

The Full Stack Guide: Connecting Angular with a .NET Backend

The Full Stack Guide: Connecting Angular with .NET ...