refactor ef core base migration in building blocks

This commit is contained in:
meysamhadeli 2022-06-24 20:10:27 +04:30
parent 34336b479f
commit 70588ebea5
13 changed files with 47 additions and 236 deletions

View File

@ -262,6 +262,7 @@ services:
elasticsearch:
container_name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.9.2
restart: unless-stopped
ports:
- 9200:9200
volumes:
@ -280,6 +281,7 @@ services:
kibana:
container_name: kibana
image: docker.elastic.co/kibana/kibana:7.9.2
restart: unless-stopped
ports:
- 5601:5601
depends_on:

View File

@ -96,6 +96,7 @@ services:
elasticsearch:
container_name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.9.2
restart: unless-stopped
ports:
- 9200:9200
volumes:
@ -114,6 +115,7 @@ services:
kibana:
container_name: kibana
image: docker.elastic.co/kibana/kibana:7.9.2
restart: unless-stopped
ports:
- 5601:5601
depends_on:

View File

@ -1,65 +0,0 @@
using System.Data;
using System.Text.Json;
using MediatR;
using Microsoft.Extensions.Logging;
namespace BuildingBlocks.EFCore;
public class EfIdentityTxBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull, IRequest<TResponse>
where TResponse : notnull
{
private readonly ILogger<EfTxBehavior<TRequest, TResponse>> _logger;
private readonly IDbContext _dbContextBase;
public EfIdentityTxBehavior(
ILogger<EfTxBehavior<TRequest, TResponse>> logger,
IDbContext dbContextBase)
{
_logger = logger;
_dbContextBase = dbContextBase;
}
public async Task<TResponse> Handle(
TRequest request,
CancellationToken cancellationToken,
RequestHandlerDelegate<TResponse> next)
{
_logger.LogInformation(
"{Prefix} Handled command {MediatrRequest}",
nameof(EfTxBehavior<TRequest, TResponse>),
typeof(TRequest).FullName);
_logger.LogDebug(
"{Prefix} Handled command {MediatrRequest} with content {RequestContent}",
nameof(EfTxBehavior<TRequest, TResponse>),
typeof(TRequest).FullName,
JsonSerializer.Serialize(request));
_logger.LogInformation(
"{Prefix} Open the transaction for {MediatrRequest}",
nameof(EfTxBehavior<TRequest, TResponse>),
typeof(TRequest).FullName);
await _dbContextBase.BeginTransactionAsync(cancellationToken);
try
{
var response = await next();
_logger.LogInformation(
"{Prefix} Executed the {MediatrRequest} request",
nameof(EfTxBehavior<TRequest, TResponse>),
typeof(TRequest).FullName);
await _dbContextBase.CommitTransactionAsync(cancellationToken);
return response;
}
catch
{
await _dbContextBase.RollbackTransactionAsync(cancellationToken);
throw;
}
}
}

View File

@ -1,5 +1,6 @@
using System.Linq.Expressions;
using BuildingBlocks.Core.Model;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Configuration;
@ -12,7 +13,7 @@ public static class Extensions
public static IServiceCollection AddCustomDbContext<TContext>(
this IServiceCollection services,
IConfiguration configuration)
where TContext : AppDbContextBase
where TContext : DbContext, IDbContext
{
services.AddDbContext<TContext>(options =>
options.UseSqlServer(
@ -24,6 +25,16 @@ public static class Extensions
return services;
}
public static IApplicationBuilder UseMigration<TContext>(this IApplicationBuilder app)
where TContext : DbContext, IDbContext
{
MigrateDatabaseAsync<TContext>(app.ApplicationServices).GetAwaiter().GetResult();
SeedDataAsync(app.ApplicationServices).GetAwaiter().GetResult();
return app;
}
// ref: https://github.com/pdevito3/MessageBusTestingInMemHarness/blob/main/RecipeManagement/src/RecipeManagement/Databases/RecipesDbContext.cs
public static void FilterSoftDeletedProperties(this ModelBuilder modelBuilder)
{
@ -41,4 +52,23 @@ public static class Extensions
mutableEntityType.SetQueryFilter(lambdaExpression);
}
}
private static async Task MigrateDatabaseAsync<TContext>(IServiceProvider serviceProvider)
where TContext : DbContext, IDbContext
{
using var scope = serviceProvider.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<TContext>();
await context.Database.MigrateAsync();
}
private static async Task SeedDataAsync(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
foreach (var seeder in seeders)
{
await seeder.SeedAllAsync();
}
}
}

View File

@ -38,7 +38,7 @@ builder.AddCustomSerilog();
builder.Services.AddJwt();
builder.Services.AddControllers();
builder.Services.AddHttpContextAccessor();
builder.Services.AddCustomSwagger(builder.Configuration, typeof(BookingRoot).Assembly);
builder.Services.AddCustomSwagger(configuration, typeof(BookingRoot).Assembly);
builder.Services.AddCustomVersioning();
builder.Services.AddCustomMediatR();
builder.Services.AddValidatorsFromAssembly(typeof(BookingRoot).Assembly);
@ -69,7 +69,7 @@ if (app.Environment.IsDevelopment())
}
app.UseSerilogRequestLogging();
app.UseMigrations();
app.UseMigration<BookingDbContext>();
app.UseCorrelationId();
app.UseRouting();
app.UseHttpMetrics();

View File

@ -1,38 +0,0 @@
using Booking.Data;
using BuildingBlocks.EFCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Booking.Extensions;
public static class MigrationsExtensions
{
public static IApplicationBuilder UseMigrations(this IApplicationBuilder app)
{
MigrateDatabase(app.ApplicationServices);
SeedData(app.ApplicationServices);
return app;
}
private static void MigrateDatabase(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<BookingDbContext>();
context.Database.Migrate();
}
private static void SeedData(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
foreach (var seeder in seeders)
{
seeder.SeedAllAsync().GetAwaiter().GetResult();
}
}
}

View File

@ -37,6 +37,7 @@ Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name));
builder.Services.AddCustomDbContext<FlightDbContext>(configuration);
builder.Services.AddScoped<IDataSeeder, FlightDataSeeder>();
builder.Services.AddMongoDbContext<FlightReadDbContext>(configuration);
builder.Services.AddPersistMessage(configuration);
@ -44,7 +45,7 @@ builder.Services.AddPersistMessage(configuration);
builder.AddCustomSerilog();
builder.Services.AddJwt();
builder.Services.AddControllers();
builder.Services.AddCustomSwagger(builder.Configuration, typeof(FlightRoot).Assembly);
builder.Services.AddCustomSwagger(configuration, typeof(FlightRoot).Assembly);
builder.Services.AddCustomVersioning();
builder.Services.AddCustomMediatR();
builder.Services.AddValidatorsFromAssembly(typeof(FlightRoot).Assembly);
@ -82,7 +83,7 @@ app.UseSerilogRequestLogging();
app.UseCorrelationId();
app.UseRouting();
app.UseHttpMetrics();
app.UseMigrations();
app.UseMigration<FlightDbContext>();
app.UseProblemDetails();
app.UseHttpsRedirection();
app.UseCustomHealthCheck();

View File

@ -1,39 +0,0 @@
using System;
using BuildingBlocks.EFCore;
using Flight.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Flight.Extensions;
public static class MigrationsExtensions
{
public static IApplicationBuilder UseMigrations(this IApplicationBuilder app)
{
MigrateDatabase(app.ApplicationServices);
SeedData(app.ApplicationServices);
return app;
}
private static void MigrateDatabase(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<FlightDbContext>();
context.Database.Migrate();
}
private static void SeedData(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
foreach (var seeder in seeders)
{
seeder.SeedAllAsync().GetAwaiter().GetResult();
}
}
}

View File

@ -27,24 +27,19 @@ var env = builder.Environment;
var appOptions = builder.Services.GetOptions<AppOptions>("AppOptions");
Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name));
builder.Services.AddScoped<IDbContext>(provider => provider.GetService<IdentityContext>()!);
builder.Services.AddDbContext<IdentityContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly(typeof(IdentityRoot).Assembly.GetName().Name)));
builder.Services.AddCustomDbContext<IdentityContext>(configuration);
builder.Services.AddScoped<IDataSeeder, IdentityDataSeeder>();
builder.Services.AddPersistMessage(configuration);
builder.AddCustomSerilog();
builder.Services.AddControllers();
builder.Services.AddCustomSwagger(builder.Configuration, typeof(IdentityRoot).Assembly);
builder.Services.AddCustomSwagger(configuration, typeof(IdentityRoot).Assembly);
builder.Services.AddCustomVersioning();
builder.Services.AddCustomMediatR();
builder.Services.AddValidatorsFromAssembly(typeof(IdentityRoot).Assembly);
builder.Services.AddCustomProblemDetails();
builder.Services.AddCustomMapster(typeof(IdentityRoot).Assembly);
builder.Services.AddScoped<IDataSeeder, IdentityDataSeeder>();
builder.Services.AddCustomHealthCheck();
builder.Services.AddTransient<IEventMapper, EventMapper>();
@ -62,7 +57,7 @@ if (app.Environment.IsDevelopment())
}
app.UseSerilogRequestLogging();
app.UseMigrations();
app.UseMigration<IdentityContext>();
app.UseCorrelationId();
app.UseRouting();
app.UseHttpMetrics();

View File

@ -13,7 +13,7 @@ public static class MediatRExtensions
services.AddMediatR(typeof(IdentityRoot).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(EfIdentityTxBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>));
return services;
}

View File

@ -1,39 +0,0 @@
using System;
using BuildingBlocks.EFCore;
using Identity.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Identity.Extensions;
public static class MigrationsExtensions
{
public static IApplicationBuilder UseMigrations(this IApplicationBuilder app)
{
MigrateDatabase(app.ApplicationServices);
SeedData(app.ApplicationServices);
return app;
}
private static void MigrateDatabase(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<IdentityContext>();
context.Database.Migrate();
}
private static void SeedData(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
foreach (var seeder in seeders)
{
seeder.SeedAllAsync().GetAwaiter().GetResult();
}
}
}

View File

@ -34,7 +34,7 @@ builder.Services.AddPersistMessage(configuration);
builder.AddCustomSerilog();
builder.Services.AddJwt();
builder.Services.AddControllers();
builder.Services.AddCustomSwagger(builder.Configuration, typeof(PassengerRoot).Assembly);
builder.Services.AddCustomSwagger(configuration, typeof(PassengerRoot).Assembly);
builder.Services.AddCustomVersioning();
builder.Services.AddCustomMediatR();
builder.Services.AddValidatorsFromAssembly(typeof(PassengerRoot).Assembly);
@ -62,7 +62,7 @@ if (app.Environment.IsDevelopment())
}
app.UseSerilogRequestLogging();
app.UseMigrations();
app.UseMigration<PassengerDbContext>();
app.UseCorrelationId();
app.UseRouting();
app.UseHttpMetrics();

View File

@ -1,38 +0,0 @@
using BuildingBlocks.EFCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Passenger.Data;
namespace Passenger.Extensions;
public static class MigrationsExtensions
{
public static IApplicationBuilder UseMigrations(this IApplicationBuilder app)
{
MigrateDatabase(app.ApplicationServices);
SeedData(app.ApplicationServices);
return app;
}
private static void MigrateDatabase(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<PassengerDbContext>();
context.Database.Migrate();
}
private static void SeedData(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
foreach (var seeder in seeders)
{
seeder.SeedAllAsync().GetAwaiter().GetResult();
}
}
}