Creating Simple CRUD Operations Using Fluent NHibernate with ASP.NET Core Web API

What Is Fluent NHibernate?

Fluent NHibernate is an extension of NHibernate, a popular Object-Relational Mapping (ORM) framework widely used in enterprise applications for database interactions. With Fluent NHibernate, developers can create mappings using a fluent API, eliminating the need for cumbersome XML configuration files.

Fluent NHibernate, paired with NHibernate, allows developers to work with database tables in an object-oriented manner while abstracting SQL interactions.

Benefits of Fluent NHibernate

Fluent NHibernate offers several advantages

  1. Simplified Configuration: It replaces XML-based mapping configurations with type-safe, fluent code, making it easier to understand and maintain.
  2. Code-First Development: Developers can define mappings directly from their domain models without relying on existing database schemas.
  3. Type Safety: Mapping is done in code, which ensures compile-time checks and reduces runtime errors.
  4. Supports Complex Relationships: Fluent NHibernate handles object relationships like inheritance and associations (one-to-many, many-to-many) with ease.
  5. Quick Prototyping: It enables rapid development by automatically generating tables using mappings when needed.

Development Steps

Let us now dive into the actual setup and implementation.

F

Step 1. Setting Up the Database Table

First, create a Users table in your database that we will use in our application.

CREATE TABLE Users(
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[FirstName] [nvarchar](255) NOT NULL,
	[LastName] [nvarchar](255) NOT NULL
);

Step 2. Creating the ASP.NET Core Web API Project

  1. Open Visual Studio.
  2. Navigate to File → New → Project, and select ASP.NET Core Web API as your project template.
  3. Configure the project details and click Create.

Step 3. Installing NHibernate NuGet Package

  1. Right-click on the solution in Solution Explorer.
  2. Select Manage NuGet Packages.
  3. Search for NHibernate and install the latest version.
  4. Repeat the process to install Fluent NHibernate.

Browse

Step 4. Setting Up the Project Structure

  1. Add a new folder named Mappings to the project.
  2. Create two files inside the project:
    • User.cs: Domain model representing the Users table.
    • UserMap.cs: Mapping file for Fluent NHibernate.
    • NHibernateHelper.cs file for database session

Here’s how your solution folder should look:

Solution explorer

Step 5. Configuring Domain Models and Mappings

User.cs (Domain Model)

Define the User class, which corresponds to the Users table.

namespace NHibernateDemo
{
    public class User
    {
        public virtual int Id { get; set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
    }
}

UserMap.cs (Mapping Configuration)

Map the User class to the Users table using Fluent NHibernate.

using FluentNHibernate.Mapping;

namespace NHibernateDemo.Mappings
{
    public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Table("Users");
            Id(x => x.Id).GeneratedBy.Identity(); // Primary Key
            Map(x => x.FirstName).Not.Nullable(); // FirstName Column
            Map(x => x.LastName).Not.Nullable();  // LastName Column
        }
    }
}

Step 6. Setting Up NHibernate Helper

Create a helper class to configure NHibernate and manage sessions.

NHibernateHelper.cs

using NHibernate;
using NHibernate.Cfg;

namespace NHibernateDemo
{
    public static class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        public static ISession OpenSession()
        {
            if (_sessionFactory == null)
            {
                var configuration = new Configuration();
                configuration.Configure(); // Configures NHibernate from hibernate.cfg.xml
                configuration.AddAssembly(typeof(User).Assembly);
                _sessionFactory = configuration.BuildSessionFactory();
            }

            return _sessionFactory.OpenSession();
        }
    }
}

Step 7. Configuring the Database Connection

Add a connection string to appsettings.json for NHibernate to connect to the database.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=NHibernateDemoDB;Trusted_Connection=True;"
  }
}

Step 8. Configuring Fluent NHibernate in Program.cs

Set up Fluent NHibernate in Program.cs for dependency injection and database schema creation.

using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// Configure Fluent NHibernate
builder.Services.AddSingleton<ISessionFactory>(provider =>
{
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

    return Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2012.ConnectionString(connectionString).ShowSql())
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<User>())
        .ExposeConfiguration(cfg =>
        {
            new SchemaExport(cfg).Create(true, true); // Automatically creates the Users table
        })
        .BuildSessionFactory();
});

builder.Services.AddScoped(provider =>
{
    return provider.GetRequiredService<ISessionFactory>().OpenSession();
});

var app = builder.Build();
app.MapControllers();
app.Run();

Step 9. Building the UsersController

Create a new controller named UsersController.cs to handle API endpoints.

UsersController.cs

using Microsoft.AspNetCore.Mvc;
using NHibernate;

namespace NHibernateDemo.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class UsersController : ControllerBase
    {
        private readonly ISession _session;

        public UsersController(ISession session)
        {
            _session = session; // NHibernate session injected
        }

        // GET: api/users
        [HttpGet]
        public IActionResult GetUsers()
        {
            var users = _session.Query<User>().ToList();
            return Ok(users);
        }

        // POST: api/users
        [HttpPost]
        public IActionResult AddUser([FromBody] User newUser)
        {
            using (var transaction = _session.BeginTransaction())
            {
                _session.Save(newUser);
                transaction.Commit();
            }
            return Ok(newUser);
        }
    }
}

Step 10. Running the Application

1. Run the project in Visual Studio.

2. Access the API endpoints using Swagger UI or Postman.

  • Use the POST endpoint (api/users) to add a user to the database.
  • Use the GET endpoint (api/users) to retrieve the list of users.

Run the project

Click on the execute button below and see the output.

Output

Now you can query the database and see the output.

Conclusion

In this article, we've implemented basic CRUD functionality using Fluent NHibernate with ASP.NET Core Web API. While we’ve demonstrated only GET and POST Methods, you can follow the same pattern for update (PUT) and delete (DELETE) operations.

This tutorial provides a solid foundation for building a robust backend API. Remember:

  • Fluent NHibernate allows for easier mapping using code-first principles.
  • Automating schema creation is suitable for prototypes but should be handled cautiously in production environments.

Thank you for reading! If you have any questions, feel free to drop a comment. Happy coding!