Rename projects to FileShare
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FileShare_EFCore.Database
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用数据库上下文基类 —— 自动根据 DatabaseConfiguration 选择数据库提供程序。
|
||||
/// 所有业务 DbContext 继承此类即可获得多数据库支持。
|
||||
/// </summary>
|
||||
public abstract class AppDbContext(DatabaseConfiguration dbConfig) : DbContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据库配置。
|
||||
/// </summary>
|
||||
private readonly DatabaseConfiguration _dbConfig = dbConfig;
|
||||
|
||||
/// <summary>
|
||||
/// 配置数据库提供程序和连接选项。
|
||||
/// </summary>
|
||||
/// <param name="optionsBuilder">选项构建器。</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据配置选择数据库提供程序。
|
||||
/// 使用注册模式,由宿主项目注册具体的提供程序实现。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存时自动设置时间戳。
|
||||
/// </summary>
|
||||
public override int SaveChanges(bool acceptAllChangesOnSuccess)
|
||||
{
|
||||
SetTimestamps();
|
||||
return base.SaveChanges(acceptAllChangesOnSuccess);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步保存更改,自动设置时间戳。
|
||||
/// </summary>
|
||||
/// <param name="acceptAllChangesOnSuccess">是否在成功时接受所有更改。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>受影响的行数。</returns>
|
||||
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
|
||||
{
|
||||
SetTimestamps();
|
||||
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动设置新增或修改实体的 CreatedAt 和 UpdatedAt 时间戳。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user