using FileShare_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 FileShare_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; }
}
}