using Avalonia_Common.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace Avalonia_EFCore.Database { /// /// 数据库管理器 —— 负责连接测试、自动迁移、种子数据、版本检查。 /// 在应用启动时调用,确保数据库结构与应用代码同步。 /// public class DatabaseManager where TContext : AppDbContext { /// /// 数据库上下文实例。 /// private readonly TContext _context; /// /// 数据库配置。 /// private readonly DatabaseConfiguration _config; /// /// DI 服务提供程序(可选,用于种子数据中解析服务)。 /// private readonly IServiceProvider? _serviceProvider; /// /// 初始化数据库管理器。 /// /// 数据库上下文。 /// 数据库配置。 /// 可选的 DI 容器。 public DatabaseManager(TContext context, DatabaseConfiguration config, IServiceProvider? serviceProvider = null) { _context = context; _config = config; _serviceProvider = serviceProvider; } /// /// 初始化数据库:测试连接 → 自动迁移 → 种子数据。 /// public async Task InitializeAsync(Action? seeder = null) { AppLog.Information( "正在初始化数据库 Provider={Provider}, AppVersion={AppVersion}", _config.Provider, GetApplicationVersion()); // 1. 自动迁移(如果启用)。MigrateAsync 会按迁移历史顺序执行全部待处理迁移, // 支持用户从较旧软件版本直接升级到当前版本。 if (_config.AutoMigrate) { if (_config.RecreateDatabase) { AppLog.Warning( "RecreateDatabase=true,将删除并重建当前连接指向的数据库。Provider={Provider}", _config.Provider); await _context.Database.EnsureDeletedAsync(); } await MigrateAsync(); } else { var canConnect = await CanConnectAsync(); if (!canConnect) { throw new InvalidOperationException( $"无法连接到数据库 [{_config.Provider}],请检查连接字符串和数据库服务状态。"); } } // 2. 种子数据 if (seeder != null) { seeder(_context, _serviceProvider); await _context.SaveChangesAsync(); } } /// /// 测试数据库连接是否正常。 /// public async Task CanConnectAsync() { try { return await _context.Database.CanConnectAsync(); } catch { return false; } } /// /// 执行待处理的迁移。 /// 使用 EF Core 原生迁移机制,自动检测并应用 Schema 变更。 /// public async Task MigrateAsync() { try { var appliedMigrations = (await _context.Database.GetAppliedMigrationsAsync()).ToList(); var pendingMigrations = await _context.Database.GetPendingMigrationsAsync(); if (pendingMigrations.Any()) { if (appliedMigrations.Count == 0) { AppLog.Information( "未检测到已应用迁移,将按当前 Provider={Provider} 从 0 构建完整表结构", _config.Provider); } AppLog.Information( "当前已应用 {AppliedCount} 个迁移,检测到 {PendingCount} 个待执行迁移: {Migrations}", appliedMigrations.Count, pendingMigrations.Count(), string.Join(", ", pendingMigrations)); await _context.Database.MigrateAsync(); AppLog.Information("数据库迁移完成({Count} 个迁移已应用)", pendingMigrations.Count()); } else { AppLog.Information("数据库已是最新版本,无需迁移"); } } catch (Exception ex) { AppLog.Error(ex, "数据库迁移失败"); throw; } } /// /// 获取当前应用程序的版本号,优先读取 AssemblyInformationalVersion,回退到 AssemblyVersion。 /// /// 应用程序版本字符串。 private static string GetApplicationVersion() { var assembly = Assembly.GetEntryAssembly() ?? typeof(TContext).Assembly; return assembly .GetCustomAttribute() ?.InformationalVersion ?? assembly.GetName().Version?.ToString() ?? "unknown"; } /// /// 获取数据库当前版本信息。 /// public async Task GetVersionInfoAsync() { var appliedMigrations = await _context.Database.GetAppliedMigrationsAsync(); var pendingMigrations = await _context.Database.GetPendingMigrationsAsync(); return new DatabaseVersionInfo { Provider = _config.Provider.ToString(), AppliedMigrations = appliedMigrations.ToList(), PendingMigrations = pendingMigrations.ToList(), IsLatest = !pendingMigrations.Any(), CanConnect = await CanConnectAsync(), }; } /// /// 生成从指定迁移到最新版本的 SQL 脚本(用于生产环境审计)。 /// public string GenerateMigrationScript(string? fromMigration = null) { var migrator = _context.GetService(); return fromMigration is null ? migrator.GenerateScript() : migrator.GenerateScript(fromMigration); } /// /// 确保数据库已创建(不执行迁移,适用于简单场景)。 /// public bool EnsureCreated() { return _context.Database.EnsureCreated(); } } /// /// 数据库版本信息 DTO。 /// public class DatabaseVersionInfo { /// /// 获取或设置数据库提供程序名称。 /// public string Provider { get; set; } = string.Empty; /// /// 获取或设置已应用的迁移列表。 /// public List AppliedMigrations { get; set; } = new(); /// /// 获取或设置待应用的迁移列表。 /// public List PendingMigrations { get; set; } = new(); /// /// 获取或设置是否为最新版本。 /// public bool IsLatest { get; set; } /// /// 获取或设置数据库是否可连接。 /// public bool CanConnect { get; set; } } }