using Microsoft.EntityFrameworkCore; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Avalonia_EFCore.Database { /// /// 应用数据库上下文基类 —— 自动根据 DatabaseConfiguration 选择数据库提供程序。 /// 所有业务 DbContext 继承此类即可获得多数据库支持。 /// public abstract class AppDbContext(DatabaseConfiguration dbConfig) : DbContext { /// /// 数据库配置。 /// private readonly DatabaseConfiguration _dbConfig = dbConfig; /// /// 配置数据库提供程序和连接选项。 /// /// 选项构建器。 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (optionsBuilder.IsConfigured) return; ConfigureProvider(optionsBuilder, _dbConfig); if (_dbConfig.EnableDetailedLog) { optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information); } // 启用详细的 EF Core 错误信息 optionsBuilder.EnableDetailedErrors(); optionsBuilder.EnableSensitiveDataLogging(_dbConfig.EnableDetailedLog); } /// /// 根据配置选择数据库提供程序。 /// 使用注册模式,由宿主项目注册具体的提供程序实现。 /// public static void ConfigureProvider(DbContextOptionsBuilder optionsBuilder, DatabaseConfiguration config) { if (DatabaseProviderRegistry.TryGet(config.Provider, out var configurator)) { configurator(optionsBuilder, config.ConnectionString, config.Timeout); } else { throw new NotSupportedException( $"数据库提供程序 {config.Provider} 未注册。" + $"请在宿主项目中安装对应的 EF Core NuGet 包并调用 DatabaseProviderRegistry.Register()。"); } optionsBuilder.EnableDetailedErrors(); optionsBuilder.EnableSensitiveDataLogging(config.EnableDetailedLog); if (config.EnableDetailedLog) { optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information); } } /// /// 保存时自动设置时间戳。 /// public override int SaveChanges(bool acceptAllChangesOnSuccess) { SetTimestamps(); return base.SaveChanges(acceptAllChangesOnSuccess); } /// /// 异步保存更改,自动设置时间戳。 /// /// 是否在成功时接受所有更改。 /// 取消令牌。 /// 受影响的行数。 public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) { SetTimestamps(); return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); } /// /// 自动设置新增或修改实体的 CreatedAt 和 UpdatedAt 时间戳。 /// private void SetTimestamps() { var entries = ChangeTracker.Entries() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified); foreach (var entry in entries) { var entity = entry.Entity; // 使用反射设置 CreatedAt / UpdatedAt(如果存在) var createdAtProp = entity.GetType().GetProperty("CreatedAt"); var updatedAtProp = entity.GetType().GetProperty("UpdatedAt"); if (entry.State == EntityState.Added && createdAtProp != null) { createdAtProp.SetValue(entity, DateTime.UtcNow); } if (updatedAtProp != null) { updatedAtProp.SetValue(entity, DateTime.UtcNow); } } } } }