using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using VOL.Core.EFDbContext; using VOL.Core.Enums; using VOL.Core.Extensions; using VOL.Entity; namespace VOL.Core.BaseProvider { public static class ApplicationServiceBaseDeleteExtensions { private static MethodInfo[] Methods { get { return typeof(ApplicationServiceBaseDeleteExtensions) .GetMethods(BindingFlags.Public | BindingFlags.Static); } } public static int DeleteWithType(this BaseDbContext dbContext, Type entityType, List keys, PropertyInfo keyPro = null, bool logicDel = true) { if (keys == null || keys.Count == 0) return 0; int delCount = 0; keyPro ??= entityType.GetKeyProperty(); var logicDelProperty = entityType.GetLogicDelPropertyWithType(); if (logicDel && logicDelProperty != null) { delCount = Methods.First(m => m.Name == nameof(LogicDelete)) .MakeGenericMethod(entityType, keyPro.PropertyType, logicDelProperty.PropertyType) .Invoke(null, [dbContext, keys, keyPro.Name, logicDelProperty]).GetInt(); } else { delCount = Methods.First(m => m.Name == nameof(Delete)) .MakeGenericMethod(entityType, keyPro.PropertyType) .Invoke(null, [dbContext, keys, keyPro.Name]).GetInt(); } return delCount; } /// /// /// /// /// /// /// /// /// public static async Task DeleteWithTypeAsync(this BaseDbContext dbContext, Type entityType, List keys, PropertyInfo keyPro = null, bool logicDel = true) { if (keys == null || keys.Count == 0) return 0; int delCount = 0; keyPro ??= entityType.GetKeyProperty(); var logicDelProperty = entityType.GetLogicDelPropertyWithType(); if (logicDel && logicDelProperty != null) { delCount = await (Methods .First(m => m.Name == nameof(LogicDeleteAsync)) .MakeGenericMethod(entityType, keyPro.PropertyType, logicDelProperty.PropertyType) .Invoke(null, [dbContext, keys, keyPro.Name, logicDelProperty]) as Task); } else { delCount = await (Methods .First(m => m.Name == nameof(DeleteAsync)) .MakeGenericMethod(entityType, keyPro.PropertyType) .Invoke(null, [dbContext, keys, keyPro.Name]) as Task); } return delCount; } /// /// 删除二、三级明细表 /// /// /// /// /// public static async Task DeleteAllDetilWithTypeAsync(this BaseDbContext dbContext, Type entityType, List keyList) { int delCount = 0; if (keyList.Count == 0) { return delCount; } var detailTypes = entityType.GetCustomAttribute()?.DetailTable ?? []; if (detailTypes.Length == 0) return delCount; foreach (var detailType in detailTypes) { //删除三级明细表 var detailFkToMain = entityType.GetForeignKeyType(detailType, detailType.Name); var subTypes = detailType.GetCustomAttribute()?.DetailTable ?? []; if (subTypes.Length > 0) { var detailKeyPro = detailType.GetKeyProperty(); var detailKeys = await dbContext.QueryKeysByForeignKeysAsync(detailType, detailKeyPro, detailFkToMain, keyList); if (detailKeys.Count > 0) { foreach (var subType in subTypes) { var subFkToDetail = detailType.GetForeignKeyType(subType, subType.Name); await dbContext.DeleteWithTypeAsync(subType, detailKeys, subFkToDetail, true); } } } //删除二级明细表 delCount += await dbContext.DeleteWithTypeAsync(detailType, keyList, detailFkToMain, true); } return delCount; } public static int DeleteAllDetilWithType(this BaseDbContext dbContext, Type entityType, List keyList) { int delCount = 0; if (keyList.Count == 0) { return delCount; } var detailTypes = entityType.GetCustomAttribute()?.DetailTable ?? []; if (detailTypes.Length == 0) return delCount; foreach (var detailType in detailTypes) { //删除三级明细表 var detailFkToMain = entityType.GetForeignKeyType(detailType, detailType.Name); var subTypes = detailType.GetCustomAttribute()?.DetailTable ?? []; if (subTypes.Length > 0) { var detailKeyPro = detailType.GetKeyProperty(); var detailKeys = dbContext.QueryKeysByForeignKeys(detailType, detailKeyPro, detailFkToMain, keyList); if (detailKeys.Count > 0) { foreach (var subType in subTypes) { var subFkToDetail = detailType.GetForeignKeyType(subType, subType.Name); dbContext.DeleteWithType(subType, detailKeys, subFkToDetail, true); } } } //删除二级明细表 delCount += dbContext.DeleteWithType(detailType, keyList, detailFkToMain, true); } return delCount; } public static int Delete(this BaseDbContext dbContext, List keys, string keyName) where TEntity : class { var expression = CreateExpression(keyName, keys); if (expression == null) return 0; return dbContext.Set().Where(expression).ExecuteDelete(); } public static async Task DeleteAsync(this BaseDbContext dbContext, List keys, string keyName) where TEntity : class { var expression = CreateExpression(keyName, keys); if (expression == null) return 0; return await dbContext.Set().Where(expression).ExecuteDeleteAsync(); } private static Expression> CreateExpression(string keyName, List keys) where TEntity : class { if (keys == null) return null; var values = keys.Where(k => k != null).Select(k => (TKey)k.ChangeType(typeof(TKey))).ToList(); if (values.Count == 0) return null; return keyName.CreateExpression(values, LinqExpressionType.In); } /// /// 逻辑删除 /// /// /// /// /// /// /// public static int LogicDelete(this BaseDbContext dbContext, List keys, string keyName, PropertyInfo logicDelProperty) where TEntity : class { var expression = CreateExpression(keyName, keys); if (expression == null) return 0; var value = (LogicFieldType)(((int)DelStatus.已删除).ChangeType(typeof(LogicFieldType))); dbContext .Set() .Where(expression) .ExecuteUpdate(c => c.SetProperty(e => EF.Property(e, logicDelProperty.Name), value)); return 0; } /// /// ??潩 /// /// /// /// /// /// /// public static async Task LogicDeleteAsync(this BaseDbContext dbContext, List keys, string keyName, PropertyInfo logicDelProperty) where TEntity : class { var expression = CreateExpression(keyName, keys); if (expression == null) return 0; var value = (LogicFieldType)(((int)DelStatus.已删除).ChangeType(typeof(LogicFieldType))); await dbContext .Set() .Where(expression) .ExecuteUpdateAsync(c => c.SetProperty(e => EF.Property(e, logicDelProperty.Name), value)); return 0; } public static async Task> QueryKeysByForeignKeysAsync( this BaseDbContext dbContext, Type entityType, PropertyInfo selectKeyProperty, PropertyInfo whereForeignKeyProperty, List foreignKeyValues) { var method = typeof(ApplicationServiceBaseDeleteExtensions) .GetMethod(nameof(QueryKeysByForeignKeysCore), BindingFlags.NonPublic | BindingFlags.Static); var generic = method.MakeGenericMethod(entityType, whereForeignKeyProperty.PropertyType, selectKeyProperty.PropertyType); var query = generic.Invoke(null, [ dbContext, whereForeignKeyProperty.Name, foreignKeyValues, selectKeyProperty.Name ]) as IQueryable; return await query.ToListAsync(); } public static List QueryKeysByForeignKeys( this BaseDbContext dbContext, Type entityType, PropertyInfo selectKeyProperty, PropertyInfo whereForeignKeyProperty, List foreignKeyValues) { var method = typeof(ApplicationServiceBaseDeleteExtensions) .GetMethod(nameof(QueryKeysByForeignKeysCore), BindingFlags.NonPublic | BindingFlags.Static); var generic = method.MakeGenericMethod(entityType, whereForeignKeyProperty.PropertyType, selectKeyProperty.PropertyType); var query = generic.Invoke(null, [ dbContext, whereForeignKeyProperty.Name, foreignKeyValues, selectKeyProperty.Name ]) as IQueryable; return query.ToList(); } private static IQueryable QueryKeysByForeignKeysCore( BaseDbContext dbContext, string whereForeignKeyName, List foreignKeyValues, string selectKeyName) where TQueryEntity : class { var values = foreignKeyValues .Where(k => k != null) .Select(k => (TWhereKey)k.ChangeType(typeof(TWhereKey))) .ToList(); var predicate = whereForeignKeyName.CreateExpression(values, LinqExpressionType.In); return dbContext.Set() .Where(predicate) .Select(e => EF.Property(e, selectKeyName)) .Select(v => (object)v); } /// /// 获取删除前的原始数据 /// /// /// /// /// public static List QueryOriginListByKeys( this BaseDbContext dbContext, List keyList, bool checkActionLog = true) where TEntity : class { if (keyList == null || keyList.Count == 0) return []; if (checkActionLog) { //没有审计日志的不记录 bool isActionLog = typeof(TEntity).IsTableActionLog(); if (!isActionLog) return null; } var keyPro = typeof(TEntity).GetKeyProperty(); var method = typeof(ApplicationServiceBaseDeleteExtensions) .GetMethod(nameof(QueryOriginListByKeysCoreAsync), BindingFlags.NonPublic | BindingFlags.Static); var generic = method.MakeGenericMethod(typeof(TEntity), keyPro.PropertyType); var query = generic.Invoke(null, [ dbContext, keyPro.Name, keyList ]) as IQueryable; return query.ToList(); } public static async Task> QueryOriginListByKeysAsync( this BaseDbContext dbContext, List keyList, bool checkActionLog = true) where TEntity : class { if (keyList == null || keyList.Count == 0) return []; if (checkActionLog) { //没有审计日志的不记录 bool isActionLog = typeof(TEntity).IsTableActionLog(); if (!isActionLog) return null; } var keyPro = typeof(TEntity).GetKeyProperty(); var method = typeof(ApplicationServiceBaseDeleteExtensions) .GetMethod(nameof(QueryOriginListByKeysCoreAsync), BindingFlags.NonPublic | BindingFlags.Static); var generic = method.MakeGenericMethod(typeof(TEntity), keyPro.PropertyType); var query = generic.Invoke(null, [ dbContext, keyPro.Name, keyList ]) as IQueryable; return await query.ToListAsync(); } private static IQueryable QueryOriginListByKeysCoreAsync( BaseDbContext dbContext, string keyName, List keyList) where TEntity : class { var values = keyList .Where(k => k != null) .Select(k => (TKey)k.ChangeType(typeof(TKey))) .ToList(); var predicate = keyName.CreateExpression(values, LinqExpressionType.In); return dbContext.Set().Where(predicate); } } }