Persistence
Overview
Independent (NO-SQL, SQL) interface for applying the storage pattern to domain logic. Dependent (NO-SQL, SQL) implementation for specific storage servers.
Install
- ASOL.Core.Persistence.Abstractions - contains persistence interfaces like IRepository, IReadOnlyRepository. Use this package when using persistence.
- ASOL.Core.Persistence.MongoDB - contains MongoDB persistence providers like MongoRepository, MongoPagedRepository, MongoPolymorphicRepository. Use this package when implementing persistence.
- ASOL.Core.Persistence.EFCore - contains EntityFrameworkCore persistence providers like BaseDynamicDbContextConfigurationProvider. Use this package when implementing persistence.
Usage third party libraries (NuGets)
ASOL.Core.Persistence.MongoDB
Registration of persistence layer
Differences of tenant, master and hybrid database contexts:
- Tenant - means that domain entity and repository is used in tenant database context only
- Master - means that domain entity and repository is used in master database context only
- Hybrid - means that domain entity and repository is used in both (tenant and master) database contexts
Required dependency injection for persistence data.
MongoDB dependency injection
Tenant, master and hybrid database context
Example for registration of repositories for tenant, master and hybrid database contexts.
services.AddMongoDb(configuration.GetSection(nameof(MongoDbConnectionOptions)));
public static IServiceCollection AddMongoDb(this IServiceCollection services, IConfigurationSection configurationSection)
{
new DbMapping().RegisterClassMaps();
services.AddDefaultTenantDbContext(configurationSection); //use tenant db context by default
services.AddRepoFactory();
// Register repositories implicitly in default context (i.e. in tenant db context only)
services.AddRepository<IBookRepository, IBookReadOnlyRepository, BookRepository>();
// Register repositories using tenant accessor (i.e. in tenant db context only)
services.AddTenantRepositoryAccessor<IBookRepository, IBookReadOnlyRepository, BookRepository>();
// Register repositories using master accessor (i.e. in master db context only)
services.AddMasterRepositoryAccessor<IBookRepository, IBookReadOnlyRepository, BookRepository>();
// Register repositories using hybrid accessor (i.e. tenant and master db contexts)
services.AddHybridRepositoryAccessor<IBookRepository, IBookReadOnlyRepository, BookRepository>();
//(ocassionally) register repositories implicitly in non-default context (i.e. in master db context only)
services.AddTransient<IBookRepository>(sp =>
{
var repoFactory = sp.GetRequiredService<IRepoFactory>();
return repoFactory.CreateMasterRepositoryByType<BookRepository>();
});
services.AddTransient<IBookReadOnlyRepository>(sp => sp.GetRequiredService<IBookRepository>());
// Data, index and seed migrations
services.AddMultitenancyMongoDbMigration();
// tenant migrations
.AddTenantDataMigration<BookDataMigration>()
// master migrations
.AddMasterDataMigration<BookDataMigration>()
// hybrid migrations
.AddHybridDataMigration<BookDataMigration>()
;
return services;
}
public class DbMapping : DbMappingBase
{
...
/// <inheritdoc/>
protected override void MapDomainEntities()
{
TryMapEntity<Book>(map =>
{
map.AutoMap();
map.SetIgnoreExtraElements(true);
});
}
...
}
Master database context
using ASxOL.MyOwnProject.Domain.Repositories;
using ASxOL.MyOwnProject.Persistence.Migrations;
using ASxOL.MyOwnProject.Persistence.Repositories;
using ASOL.Core.Multitenancy.MongoDb.Extensions;
using ASOL.Core.Persistence.MongoDb.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ASxOL.MyOwnProject.Persistence;
public static class MongoDbServiceCollectionExtensions
{
public static IServiceCollection AddMongoDb(this IServiceCollection services, IConfigurationSection configurationSection)
{
new DbMapping().RegisterClassMaps();
services.TryAddDefaultMasterDbContext();
services.TryAddMasterRepoFactory();
services.AddMasterRepositoryAccessor<ITestItemRepository, ITestItemReadOnlyRepository, TestItemRepository>();
return services;
}
}
EntityFrameworkCore (EfCore) dependency injection
Tenant database context
services.AddEfCorePersistence<DatabaseContextConfigurationProvider>();
public static IServiceCollection AddEfCorePersistence<TTenantDbContextConfigurationProvider>(this IServiceCollection services)
where TTenantDbContextConfigurationProvider : class, ITenantDbContextConfigurationProvider
{
services.AddTenantDbContext<DatabaseContext, TTenantDbContextConfigurationProvider>();
services.AddTenantRepositoryAccessor<ITestItemRepository, ITestItemReadOnlyRepository, TestItemRepository, DatabaseContext>();
return services;
}
Master database context
services.AddEfCorePersistence<DatabaseContextConfigurationProvider>();
public static IServiceCollection AddEfCorePersistence<TMasterDbContextConfigurationProvider>(this IServiceCollection services)
where TMasterDbContextConfigurationProvider : class, IMasterDbContextConfigurationProvider
{
services.AddMasterDbContext<DatabaseContext, TMasterDbContextConfigurationProvider>();
services.AddMasterRepositoryAccessor<ITestItemRepository, ITestItemReadOnlyRepository, TestItemRepository, DatabaseContext>();
return services;
}
Hybrid database context
services.AddEfCorePersistence<TenantDatabaseContextConfigurationProvider, MasterDatabaseContextConfigurationProvider>();
public static IServiceCollection AddEfCorePersistence<TTenantDbContextConfigurationProvider, TMasterDbContextConfigurationProvider>(this IServiceCollection services)
where TTenantDbContextConfigurationProvider : class, ITenantDbContextConfigurationProvider
where TMasterDbContextConfigurationProvider : class, IMasterDbContextConfigurationProvider
{
services.AddHybridDbContext<DatabaseContext, TTenantDbContextConfigurationProvider, TMasterDbContextConfigurationProvider>();
services.AddHybridRepositoryAccessor<ITestItemRepository, ITestItemReadOnlyRepository, TestItemRepository, DatabaseContext>();
return services;
}