using System.Linq.Expressions; using BuildingBlocks.Core.Model; using BuildingBlocks.PersistMessageProcessor.Data; using BuildingBlocks.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace BuildingBlocks.EFCore; public static class Extensions { public static IServiceCollection AddCustomDbContext( this IServiceCollection services) where TContext : DbContext, IDbContext { services.AddOptions() .BindConfiguration(nameof(DatabaseOptions)) .ValidateDataAnnotations(); services.AddDbContext((sp, options) => { var databaseOptions = services.GetOptions(nameof(DatabaseOptions)); options.UseSqlServer(databaseOptions?.DefaultConnection, dbOptions => { dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name); }); }); services.AddScoped(provider => provider.GetService()); return services; } public static IApplicationBuilder UseMigration(this IApplicationBuilder app, IWebHostEnvironment env) where TContext : DbContext, IDbContext { MigrateDatabaseAsync(app.ApplicationServices).GetAwaiter().GetResult(); if (!env.IsEnvironment("test")) 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) { Expression> filterExpr = e => !e.IsDeleted; foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes() .Where(m => m.ClrType.IsAssignableTo(typeof(IAudit)))) { // modify expression to handle correct child type var parameter = Expression.Parameter(mutableEntityType.ClrType); var body = ReplacingExpressionVisitor .Replace(filterExpr.Parameters.First(), parameter, filterExpr.Body); var lambdaExpression = Expression.Lambda(body, parameter); // set filter mutableEntityType.SetQueryFilter(lambdaExpression); } } private static async Task MigrateDatabaseAsync(IServiceProvider serviceProvider) where TContext : DbContext, IDbContext { using var scope = serviceProvider.CreateScope(); var persistMessageContext = scope.ServiceProvider.GetRequiredService(); await persistMessageContext.Database.MigrateAsync(); var context = scope.ServiceProvider.GetRequiredService(); await context.Database.MigrateAsync(); } private static async Task SeedDataAsync(IServiceProvider serviceProvider) { using var scope = serviceProvider.CreateScope(); var seeders = scope.ServiceProvider.GetServices(); foreach (var seeder in seeders) { await seeder.SeedAllAsync(); } } }