90 lines
3.4 KiB
C#
90 lines
3.4 KiB
C#
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using TakeoutSaaS.Infrastructure.Common.Options;
|
||
using TakeoutSaaS.Infrastructure.Common.Persistence;
|
||
using TakeoutSaaS.Shared.Abstractions.Data;
|
||
|
||
namespace TakeoutSaaS.Infrastructure.Common.Extensions;
|
||
|
||
/// <summary>
|
||
/// 数据访问与多数据源相关的服务注册扩展。
|
||
/// </summary>
|
||
public static class DatabaseServiceCollectionExtensions
|
||
{
|
||
/// <summary>
|
||
/// 注册数据库基础设施(多数据源配置、读写分离、Dapper 执行器)。
|
||
/// </summary>
|
||
/// <param name="services">服务集合。</param>
|
||
/// <param name="configuration">配置源。</param>
|
||
/// <returns>服务集合。</returns>
|
||
public static IServiceCollection AddDatabaseInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||
{
|
||
services.AddOptions<DatabaseOptions>()
|
||
.Bind(configuration.GetSection(DatabaseOptions.SectionName))
|
||
.ValidateDataAnnotations()
|
||
.ValidateOnStart();
|
||
|
||
services.AddSingleton<IDatabaseConnectionFactory, DatabaseConnectionFactory>();
|
||
services.AddScoped<IDapperExecutor, DapperExecutor>();
|
||
return services;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为指定 DbContext 注册读写分离的 PostgreSQL 配置,同时提供读上下文工厂。
|
||
/// </summary>
|
||
/// <typeparam name="TContext">上下文类型。</typeparam>
|
||
/// <param name="services">服务集合。</param>
|
||
/// <param name="dataSourceName">逻辑数据源名称。</param>
|
||
/// <returns>服务集合。</returns>
|
||
public static IServiceCollection AddPostgresDbContext<TContext>(
|
||
this IServiceCollection services,
|
||
string dataSourceName)
|
||
where TContext : DbContext
|
||
{
|
||
services.AddDbContext<TContext>(
|
||
(sp, options) =>
|
||
{
|
||
ConfigureDbContextOptions(sp, options, dataSourceName, DatabaseConnectionRole.Write);
|
||
},
|
||
contextLifetime: ServiceLifetime.Scoped,
|
||
optionsLifetime: ServiceLifetime.Singleton);
|
||
|
||
services.AddDbContextFactory<TContext>((sp, options) =>
|
||
{
|
||
ConfigureDbContextOptions(sp, options, dataSourceName, DatabaseConnectionRole.Read);
|
||
});
|
||
|
||
return services;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 配置 DbContextOptions,应用连接串、命令超时与重试策略。
|
||
/// </summary>
|
||
/// <param name="serviceProvider">服务提供程序。</param>
|
||
/// <param name="optionsBuilder">上下文配置器。</param>
|
||
/// <param name="dataSourceName">数据源名称。</param>
|
||
/// <param name="role">连接角色。</param>
|
||
private static void ConfigureDbContextOptions(
|
||
IServiceProvider serviceProvider,
|
||
DbContextOptionsBuilder optionsBuilder,
|
||
string dataSourceName,
|
||
DatabaseConnectionRole role)
|
||
{
|
||
var connection = serviceProvider
|
||
.GetRequiredService<IDatabaseConnectionFactory>()
|
||
.GetConnection(dataSourceName, role);
|
||
|
||
optionsBuilder.UseNpgsql(
|
||
connection.ConnectionString,
|
||
npgsqlOptions =>
|
||
{
|
||
npgsqlOptions.CommandTimeout(connection.CommandTimeoutSeconds);
|
||
npgsqlOptions.EnableRetryOnFailure(
|
||
connection.MaxRetryCount,
|
||
TimeSpan.FromSeconds(connection.MaxRetryDelaySeconds),
|
||
null);
|
||
});
|
||
}
|
||
}
|