Files
WCS/Cowain.TestProject/DBContext/DBContextGenerator.cs
2026-03-02 09:08:20 +08:00

170 lines
5.6 KiB
C#

using Avalonia.Controls;
using Cowain.Base.DBContext;
using Cowain.Base.Helpers;
using Cowain.Base.Models;
using Cowain.TestProject.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using static Azure.Core.HttpHeader;
namespace Cowain.TestProject.DBContext;
/// <summary>
/// 数据库生成使用,代码中不要使用,不要注入到容器
/// </summary>
public class DBContextGenerator : DbContext
{
private readonly string? _dbType;
private IConfiguration? _configuration;
private List<Assembly>? _assemblies;
public DBContextGenerator()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
_configuration = configuration;
_dbType = configuration.GetSection("Database")["db"];
_assemblies = [.. GetAssembliesFromPluginDirectory()];
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
if (string.IsNullOrEmpty(_dbType))
{
return;
}
if (!Enum.TryParse<DataBaseType>(_dbType.ToUpper(), out var cmdType))
{
return;
}
if (_configuration == null)
{
return;
}
switch (cmdType)
{
case DataBaseType.SQLITE:
var SqlLite_connection = _configuration.GetConnectionString("SqlLiteConn");
options.UseSqlite(SqlLite_connection);
break;
case DataBaseType.SQLSERVER:
var SqlServer_connection = _configuration.GetConnectionString("SqlServerConn");
options.UseSqlServer(SqlServer_connection);
break;
case DataBaseType.MYSQL:
var MySql_connection = _configuration.GetConnectionString("MySqlConn");
options.UseMySql(MySql_connection, new MySqlServerVersion(new Version(8, 0, 26)));
break;
case DataBaseType.POSTGRES:
var Postgres_connection = _configuration.GetConnectionString("PostGresConn");
options.UseNpgsql(Postgres_connection);
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
break;
}
options.ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.PendingModelChangesWarning));
options.EnableSensitiveDataLogging();
}
override protected void OnModelCreating(ModelBuilder modelBuilder)
{
MapModelEntities(modelBuilder);
DataSeeding(modelBuilder);
base.OnModelCreating(modelBuilder);
modelBuilder.Ignore<SerilogDto>();
}
/// <summary>
/// Auto data seeding
/// </summary>
/// <param name="modelBuilder">ModelBuilder</param>
private void DataSeeding(ModelBuilder modelBuilder)
{
var baseModelType = typeof(IDataSeeding);
var entityTypes = _assemblies?
.SelectMany(assembly => assembly.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && baseModelType.IsAssignableFrom(t));
if (entityTypes == null)
{
return;
}
foreach (var type in entityTypes)
{
var instance = Activator.CreateInstance(type) as IDataSeeding;
instance?.DataSeeding(modelBuilder);
}
}
/// <summary>
/// Auto Mapping Entity
/// </summary>
/// <param name="modelBuilder">ModelBuilder</param>
private void MapModelEntities(ModelBuilder modelBuilder)
{
var baseModelType = typeof(BaseModel);
var entityTypes = _assemblies?
.SelectMany(assembly => assembly.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(baseModelType));
if (entityTypes == null)
{
return;
}
foreach (var type in entityTypes)
{
modelBuilder.Model.AddEntityType(type);
}
}
/// <summary>
/// Get all assemblies including those in the plugin directory
/// </summary>
/// <returns>IEnumerable<Assembly></returns>
private IEnumerable<Assembly> GetAssembliesFromPluginDirectory()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
var pluginPath = Path.Combine(AppContext.BaseDirectory, "Plugins");
// 处理加载失败的情况
if (Directory.Exists(pluginPath))
{
var pluginAssemblies = Directory.GetFiles(pluginPath, "Plugin.*.dll", SearchOption.AllDirectories)
.Select(Assembly.LoadFrom);
assemblies.AddRange(pluginAssemblies);
}
return assemblies;
}
/// <summary>
/// create DbSet
/// </summary>
/// <typeparam name="T">Entity</typeparam>
/// <returns></returns>
public virtual DbSet<T> GetDbSet<T>() where T : class
{
if (Model.FindEntityType(typeof(T)) != null)
{
return Set<T>();
}
else
{
throw new Exception($"type {typeof(T).Name} is not add into DbContext ");
}
}
/// <summary>
/// over write EnsureCreated
/// </summary>
/// <returns></returns>
public virtual bool EnsureCreated()
{
return Database.EnsureCreated();
}
}