using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Mirea.Api.DataAccess.Application.Interfaces.DbContexts.Schedule; using Mirea.Api.DataAccess.Domain.Schedule; using Mirea.Api.DataAccess.Persistence.Common; using Mirea.Api.DataAccess.Persistence.Contexts.Schedule; using Mirea.Api.DataAccess.Persistence.EntityTypeConfigurations; using System; using System.Linq; using System.Reflection; namespace Mirea.Api.DataAccess.Persistence; public static class DependencyInjection { public static IServiceCollection AddPersistence(this IServiceCollection services, DatabaseProvider dbProvider, string connection) { services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => UseDatabase(options).CreateDbContext(dbProvider)); services.AddDbContext(options => { var providerNamespace = typeof(Mark).Namespace + "." + Enum.GetName(dbProvider); var assembly = Assembly.GetExecutingAssembly(); var configurationTypes = assembly.GetTypes() .Where(t => t is { IsNested: false, IsAbstract: false, Namespace: not null } && t.Namespace.StartsWith(providerNamespace) && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))); var modelBuilder = new ModelBuilder(); foreach (var configurationType in configurationTypes) { var configurationInstance = Activator.CreateInstance(configurationType)!; modelBuilder.ApplyConfiguration(configurationInstance); } var dbContext = (UberDbContext)Activator.CreateInstance(typeof(UberDbContext), (DbContextOptions)UseDatabase(options).Options)!; dbContext.ApplyConfigurations(modelBuilder); }); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); services.AddScoped(provider => provider.GetRequiredService()); return services; DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder options) { return dbProvider switch { DatabaseProvider.Mysql => options.UseMySql(connection, ServerVersion.AutoDetect(connection), x => x.MigrationsAssembly("MysqlMigrations")), DatabaseProvider.Sqlite => options.UseSqlite(connection, x => x.MigrationsAssembly("SqliteMigrations")), DatabaseProvider.Postgresql => options.UseNpgsql(connection, x => x.MigrationsAssembly("PsqlMigrations")), _ => throw new ArgumentException("Unsupported database provider", Enum.GetName(dbProvider)) }; } } public static IHealthChecksBuilder AddDatabaseHealthCheck(this IHealthChecksBuilder healthChecksBuilder, DatabaseProvider dbProvider, string connection) { return dbProvider switch { DatabaseProvider.Mysql => healthChecksBuilder.AddMySql(connection, name: "MySql"), DatabaseProvider.Sqlite => healthChecksBuilder.AddSqlite(connection, name: "Sqlite"), DatabaseProvider.Postgresql => healthChecksBuilder.AddNpgSql(connection, name: "PostgreSQL"), _ => throw new ArgumentException("Unsupported database provider", Enum.GetName(dbProvider)) }; } }