using Furion;
using Furion.DatabaseAccessor;
using Furion.DistributedIDGenerator;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace FlexJobApi.Core
{
public static class DbUtils
{
///
/// 生成实体注释
///
///
///
///
public static async Task BuildEntityComment(ModelBuilder modelBuilder, Type dbContextLocator = null)
{
var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
var entityTypes = App.Assemblies
.Where(it => it.FullName.Contains("FlexJob"))
.SelectMany(it => it.GetTypes())
.Where(it =>
it.IsClass
&& !it.IsAbstract
&& typeof(IPrivateEntity).IsAssignableFrom(it)
&& (dbContextLocator == null
? it.BaseType == typeof(CommonEntity)
: it.BaseType.GenericTypeArguments.Any(it => it == dbContextLocator)))
.ToList();
foreach (var entityType in entityTypes)
{
Console.WriteLine($"正在生成表:{entityType.Name}");
// 获取实体类的XML注释,并设置为表注释
var entityBuilder = modelBuilder.Entity(entityType);
string typeComment = (await entityType.GetXmlDocMemberAsync(xmlDoc))?.Summary;
if (!string.IsNullOrEmpty(typeComment))
{
Console.WriteLine($"正在生成表注释:{entityType.Name}-{typeComment}");
entityBuilder.ToTable(it => it.HasComment(typeComment));
}
// 获取实体属性的XML注释,并设置为列注释
var properties = entityType.GetProperties()
.Where(p =>
p.CanRead
&& p.CanWrite
&& !typeof(System.Collections.ICollection).IsAssignableFrom(p.PropertyType)
&& (p.PropertyType.IsClass ? p.PropertyType.FullName.Contains("System.") : true));
foreach (var property in properties)
{
string propComment = (await property.GetXmlDocMemberAsync(xmlDoc))?.Summary;
if (!string.IsNullOrEmpty(propComment))
{
Console.WriteLine($"正在生成属性注释:{property.Name}-{propComment}");
entityBuilder.Property(property.Name).HasComment(propComment);
}
}
}
}
public static void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result)
{
// 获取当前事件对应上下文
var dbContext = eventData.Context;
// 强制重新检查一边实体更改信息
// dbContext.ChangeTracker.DetectChanges();
// 获取所有更改,删除,新增的实体
var dbAuditLogIgnoreType = typeof(IDbAuditLogIgnore);
var physicalDeletionType = typeof(IPhysicalDeletion);
var entities = dbContext.ChangeTracker.Entries()
.Where(u =>
u.GetType() != typeof(DbAuditLog)
&& (u.State == EntityState.Modified
|| u.State == EntityState.Deleted
|| u.State == EntityState.Added))
.ToList();
// 通过请求中获取当前操作人
var logier = JwtUtils.GetCurrentLogier();
// 获取所有已更改的实体
foreach (var entity in entities)
{
// 获取实体类型
var entityType = entity.Entity.GetType();
if (entity.State == EntityState.Added)
{
// 赋值创建日期
var prop = entity.Property(nameof(CommonEntity.CreatedTime));
if (prop != null && prop.CurrentValue?.ToDateTime() == null)
{
prop.CurrentValue = DateTimeOffset.Now;
}
// 生成Id
prop = entity.Property(nameof(CommonEntity.Id));
var defaultValue = Activator.CreateInstance(prop.Metadata.ClrType);
if (prop != null && (prop.CurrentValue == null || prop.CurrentValue.Equals(defaultValue)))
{
prop.CurrentValue = IDGen.NextID();
}
// 赋值用户信息Id
prop = entity.Property(nameof(CommonEntity.CreatedUserInfoId));
if (prop != null && prop.CurrentValue == null)
{
prop.CurrentValue = logier?.UserInfoId;
}
}
else
{
// 赋值修改日期
var prop = entity.Property(nameof(CommonEntity.UpdatedTime));
if (prop != null && prop.CurrentValue?.ToDateTime() == null)
{
prop.CurrentValue = DateTimeOffset.Now;
}
// 赋值用户信息Id
prop = entity.Property(nameof(CommonEntity.UpdatedUserInfoId));
if (prop != null && prop.CurrentValue == null)
{
prop.CurrentValue = logier?.UserInfoId;
}
// 赋值跟踪Id
prop = entity.Property(nameof(CommonEntity.TraceId));
if (prop != null && prop.CurrentValue == null)
{
prop.CurrentValue = App.GetTraceId();
}
// 软删除
if (entity.State == EntityState.Deleted && !physicalDeletionType.IsAssignableFrom(entityType))
{
entity.State = EntityState.Modified;
prop = entity.Property(nameof(CommonEntity.IsDeleted));
if (prop != null && prop.CurrentValue == null)
{
prop.CurrentValue = true;
}
}
}
if (dbAuditLogIgnoreType.IsAssignableFrom(entityType))
{
continue;
}
Db.GetRepository().InsertNow(new DbAuditLog
{
Id = IDGen.NextID(),
TableName = entityType.Name,
PrimaryKey = (Guid)entity.Property("Id").CurrentValue,
NewValues = entity.State == EntityState.Added || entity.State == EntityState.Modified
? GetPropertyValuesAsJson(entity)
: null,
OldValues = entity.State == EntityState.Deleted || entity.State == EntityState.Modified
? GetPropertyValuesAsJson(entity, entity.State == EntityState.Modified)
: null,
Operate = entity.State == EntityState.Added
? EnumDbAuditOperate.Added
: entity.State == EntityState.Modified
? EnumDbAuditOperate.Modified
: EnumDbAuditOperate.Deleted,
TraceId = App.GetTraceId(),
CreatedTime = DateTime.Now,
CreatedUserInfoId = logier?.UserInfoId,
});
}
}
private static string GetPropertyValuesAsJson(EntityEntry entry, bool getOldValues = false)
{
var properties = entry.Properties
.Where(p => getOldValues ? p.IsModified : true)
.ToDictionary(p => p.Metadata.Name, p => getOldValues ? p.OriginalValue : p.CurrentValue);
return JsonConvert.SerializeObject(properties);
}
public static void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)
{
var metadata = entityBuilder.Metadata;
var parameter = Expression.Parameter(metadata.ClrType, "e");
var property = Expression.Property(parameter, nameof(CommonEntity.IsDeleted));
var falseConstant = Expression.Constant(false, typeof(bool));
var fakeDeleteQueryFilterExpression = Expression.Lambda(
Expression.Equal(property, falseConstant),
parameter
);
if (fakeDeleteQueryFilterExpression == null) return;
entityBuilder.HasQueryFilter(fakeDeleteQueryFilterExpression);
}
}
}