Skip to content

Persistence Module

The Persistence Module includes basic types and utilities for persisting entities into relational databases.

The actual connection to the DB is done through an ORM. There are two persistence implementations: one using NHibernate, and another using Entity Framework Core.

The NHibernate module is quasi deprecated; it is kept for the hope that it might be helpful in a migration phase, but its code is not really production ready nor tested.

Important

For new services, we recommend starting using Entity Framework Core instead of NHibernate. The main reasons being that it integrates better with the .NET ecosystem and its packages; and it being kind of a standard in .NET, there's more resources, documentation, articles, etc.

The entirety of this documentation will refer exclusively to EFCore, since that is what we want to use from now on.

Bear in mind that despite of the ORM we use, all of the persistence code should be on the Infrastructure Layer and only repository interfaces are exposed. So if we ever decide to make drastic changes, they will be isolated to the infrastructure layer.

EFCore Implementation

We recommend creating a new module for your persistence layer, in order to keep it clean. We recommend you either:

  1. For small microservices, create a new Infrastructure folder and a new YourServicePersistenceModule Suite Module inside it.
  2. If it's too large, or if you wanna have a clean separation of concerns, you may create a new project using the provided Suite Modules template.

Whatever approach you decide to go, the rules for the infrastructure layer still applies; it's just convenience. From the infrastructure layer, you may only reference domain objects, and never application/other objects.

Now, in your own persistence module, you would depend on the required modules to compose your persistence layer, for example:

C#
internal class ServiceOrderPersistenceModule : SuiteModule
{
    public override void SetupModule(IModuleBuilder builder)
    {
        base.SetupModule(builder);

        // Adds Unit of Work per Request middleware (our classic "session per request" middleware)
        builder.DependsOn<AspNetPersistenceModule>();

        // Depend on EntityFramework (instead of NHibernate)
        builder.DependsOn<EntityFrameworkCoreModule>();

        // Depend on SqlServer. Each DB Provider has a different module.
        // More on this on Multi DBMS support
        builder.DependsOn<EntityFrameworkCoreSqlServerModule>();
    }
}

In order to dive deeper, please see the following topics which cover how to declare entities, class mappings, repositories, and more.

Multi-DBMS support

The EFCore module supports using multiple Database Providers. Currently, implementations for SqlServer and Sqlite are provided. Oracle is being worked on.

Applications may customize their repositories to make them specific for a DB provider. This allows them to have custom queries / symbols used only on that provider.

In order to support this pattern, provider specific code must be placed in a different Suite Module and assembly.

Tip

When using the microservice template, this is setup automatically for you.

In order to add support for a new provider to an existing service we need to:

Add a new module for the provider:

Bash
1
2
3
dotnet new suitemodule \
    -n ITsynch.Suite.{ServiceName}.Persistence.SqlServerProvider \
    -o src/services/{ServiceName}/ITsynch.Suite.{ServiceName}.Persistence.SqlServerProvider`

We then need to depend on the EFCore Provider Module for our DB provider, for example the EntityFrameworkCoreSqlServerModule

C#
internal class ServiceNameSqlServerProviderModule : SuiteModule
{
    public override void SetupModule(IModuleBuilder builder)
    {
        base.SetupModule(builder);

        // Depend on our provider
        builder.DependsOn<EntityFrameworkCoreSqlServerModule>();
    }
}

Then we need to depend on our new module in our Application module.

To choose a DB provider, we can use IConfiguration, i.e:

JSON
1
2
3
4
5
{
    "ITsynch.Suite.App.Modules.EntityFrameworkCoreModuleOptions": {
        "DefaultDatabaseProviderKey": "SqlServer"
    }
}

Read more on the Configuration Section