Skip to content

EngineBay.Persitence module for storing data in databases

License

Notifications You must be signed in to change notification settings

engine-bay/persistence

Repository files navigation

EngineBay.Persistence

NuGet version Maintainability Test Coverage

Persistence module for EngineBay published to EngineBay.Persistence on NuGet.

About

The persistence module provides structures to configure and register any database connections that modules in your application might need.

The DbContexts from this module should be inherited by the DbContexts of any module that needs to use a database. To support Command and Query Responsibility Segregation (CQRS), a read-optimised and a write-optimised DbContext are provided - though a general-purpose one is also provided.

The TimestampInterceptor will add creation and modification timestamps to any model that implements EngineBay.Core's BaseModel.

The AuditableModel abstract class will provide some standard fields for tracking which users make changes to any inheriting models. If changes are saved on a DbContext that uses EngineBay.Auditing's AuditInterceptor, then audit entries will automatically be created for any models that implement AuditableModel.

ApplicationUser is a simple representation of a user for the application. It has a DbSet provided in ModuleDbContext so that any module inheriting these contexts will have access to the application users. ApplicationUser implements AuditableModel.

Usage

To use this module in your own, you will need to create three DbContexts - generic, read, and write - so that they can be registered. With the currently preferred structure, they will need to inherit from the Persistence DbContexts in a chain like shown in this diagram (using EngineBay.Blueprints module as an example):

%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart BT
    BlueprintsWriteDbContext --> BlueprintsQueryDbContext
    BlueprintsQueryDbContext --> BlueprintsDbContext
    BlueprintsDbContext --> ModuleWriteDbContext
    ModuleWriteDbContext --> ModuleQueryDbContext
    ModuleQueryDbContext --> ModuleDbContext
    click ModuleDbContext "https://github.com/engine-bay/persistence/blob/feature/readmes/EngineBay.Persistence/DbContexts/ModuleDbContext.cs" _blank
    click ModuleQueryDbContext "https://github.com/engine-bay/persistence/blob/feature/readmes/EngineBay.Persistence/DbContexts/ModuleQueryDbContext.cs" _blank
    click ModuleWriteDbContext "https://github.com/engine-bay/persistence/blob/feature/readmes/EngineBay.Persistence/DbContexts/ModuleWriteDbContext.cs" _blank
    click BlueprintsDbContext "https://github.com/engine-bay/blueprints/blob/main/EngineBay.Blueprints/Persistence/BlueprintsDbContext.cs" _blank
    click BlueprintsQueryDbContext "https://github.com/engine-bay/blueprints/blob/main/EngineBay.Blueprints/Persistence/BlueprintsQueryDbContext.cs" _blank
    click BlueprintsWriteDbContext "https://github.com/engine-bay/blueprints/blob/main/EngineBay.Blueprints/Persistence/BlueprintsWriteDbContext.cs" _blank

You should register your DbSets only in your generic DbContext:

namespace EngineBay.Blueprints
{
    using EngineBay.Persistence;
    using Microsoft.EntityFrameworkCore;

    public class BlueprintsDbContext : ModuleWriteDbContext
    {
        public BlueprintsDbContext(DbContextOptions<ModuleWriteDbContext> options)
            : base(options)
        {
        }

        public DbSet<Workbook> Workbooks { get; set; } = null!;

        public DbSet<Blueprint> Blueprints { get; set; } = null!;

        // More DbSets...

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            Workbook.CreateDataAnnotations(modelBuilder);
            Blueprint.CreateDataAnnotations(modelBuilder);
            // More annotations...

            base.OnModelCreating(modelBuilder);
        }
    }
}

If you desire extra functionality for any of the contexts, such as an auditing interceptor from EngineBay.Auditing, you can access the options builder with the OnConfiguring method, like this:

namespace EngineBay.Blueprints
{
    using EngineBay.Auditing;
    using EngineBay.Persistence;
    using Microsoft.EntityFrameworkCore;

    public class BlueprintsWriteDbContext : BlueprintsQueryDbContext
    {
        private readonly IAuditingInterceptor auditingInterceptor;

        public BlueprintsWriteDbContext(DbContextOptions<ModuleWriteDbContext> options, IAuditingInterceptor auditingInterceptor)
            : base(options)
        {
            this.auditingInterceptor = auditingInterceptor;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            ArgumentNullException.ThrowIfNull(optionsBuilder);

            optionsBuilder.AddInterceptors(this.auditingInterceptor);

            base.OnConfiguring(optionsBuilder);
        }
    }
}

When you've created your module's DbContexts, you will need to create a CQRSDatabaseConfiguration object in your module's setup class that will register the contexts. For example:

namespace EngineBay.Blueprints
{
    using EngineBay.Core;
    using EngineBay.Persistence;
    using FluentValidation;

    public class BlueprintsModule : BaseModule
    {
        public override IServiceCollection RegisterModule(IServiceCollection services, IConfiguration configuration)
        {
            // Other services registration...

            var databaseConfiguration = new CQRSDatabaseConfiguration<BlueprintsDbContext, BlueprintsQueryDbContext, BlueprintsWriteDbContext>();
            databaseConfiguration.RegisterDatabases(services);

            return services;
        }

        // Other setup methods...
    }
}

You will then be able to use your DbContexts freely, as you might any other DbContext, though do try to keep CQRS principals in mind.

Registration

This module cannot run on its own. You will need to register it in your application to use its functionality. See the Demo API registration guide.

Note that you do not need to register the Persistence DbContexts. The ApplicationUsers DbSet that these contexts provide will be available to any other module's DbContexts by virtue of inheritance.

Environment Variables

See the Documentation Portal.

Dependencies

About

EngineBay.Persitence module for storing data in databases

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages