using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; using VOL.Core.Configuration; using VOL.Core.DBManager; using VOL.Core.Enums; using VOL.Core.Extensions; using VOL.Core.Tenancy; using VOL.Entity.DomainModels; using VOL.Entity.SystemModels; namespace VOL.Core.BaseProvider { public static class ApplicationServiceBaseSearchExtensions { public static (IQueryable queryable, Dictionary orderbyDic) BuildPageDataQuery( this PageDataOptions options, ServiceBase service, bool useTenancy = true, bool logicDel = true) where TEntity : BaseEntity where TRepository : IRepository { //生成查询条件与数据权限过滤 IQueryable queryable = service.ValidatePageOptions(options, useTenancy); //获取排序字段 var properties = typeof(TEntity).GetProperties(); Dictionary orderbyDic = service.GetPageDataSort(options, properties); if (service.QueryRelativeExpression != null) { queryable = service.QueryRelativeExpression.Invoke(queryable); } //过滤逻辑删除 if (logicDel) { queryable = queryable.FilterLogicDel(); } return (queryable, orderbyDic); } public static IQueryable ValidatePageOptions( this ServiceBase service, PageDataOptions options, bool useTenancy = true) where TEntity : BaseEntity where TRepository : IRepository { if (options.Rows <= 0) { options.Rows = 30; } List searchParametersList = options.GetSearchParameters(); service.QueryRelativeList?.Invoke(searchParametersList); IQueryable queryable = null; if (useTenancy && options.Value?.ToString() != "viewflow") { queryable = GetSearchQueryable(service); } else { queryable = service.repository.DbContext.Set(); } queryable = options.ConvertQueryFilter(queryable); //options.TableName = typeof(TEntity).Name; return queryable; } /// /// 自定义原生查询sql或多租户(查询、导出) /// /// private static IQueryable GetSearchQueryable(ServiceBase service) where TEntity : BaseEntity where TRepository : IRepository { if (!string.IsNullOrEmpty(service.QuerySql)) { var customerQueryable = service.repository.DbContext.Set().FromSqlRaw(service.QuerySql); service.QuerySql = null; return service.GetSearchQueryable(customerQueryable); } var query = service.repository.DbContext.Set(); if (!service.IsMultiTenancy) { return query; } return service.GetSearchQueryable(query); } public static IQueryable GetSearchQueryable( this ServiceBase service, IQueryable queryable) where TEntity : BaseEntity where TRepository : IRepository { string tableName = typeof(TEntity).GetEntityTableName(); var sql = TenancyManager.GetSearchQueryable(tableName); if (!string.IsNullOrEmpty(sql)) { return service.repository.DbContext.Set().FromSqlRaw(sql); } return queryable; } public static IQueryable GetSearchQueryable(this PageDataOptions options, bool useTenancy = true, bool logicDel = true) where TEntity : class { var queryable = options.ConvertQueryFilter(); if (logicDel) { queryable = queryable.FilterLogicDel(); } return queryable; } public static List GetSearchParameters(this PageDataOptions options) { List searchParametersList = []; if (options.Filter != null && options.Filter.Count > 0) { searchParametersList.AddRange(options.Filter); } else if (!string.IsNullOrEmpty(options.Wheres)) { try { searchParametersList = options.Wheres.DeserializeObject>(); options.Filter = searchParametersList; } catch { } } return searchParametersList; } public static IQueryable ConvertQueryFilter(this PageDataOptions options, IQueryable queryable = null) where TEntity : class { queryable ??= DBServerProvider.DbContext.Set(); List searchParametersList = options.GetSearchParameters(); if (searchParametersList == null) { return queryable; } var TProperties = typeof(TEntity).GetProperties(); Expression> BuildExpression(SearchParameters x) { // 空或null值查询条件 if (Enum.TryParse(x.DisplayType, ignoreCase: true, out LinqExpressionType filterType)) { if (filterType.CheckFilterNullExpression()) { return x.Name.CreateExpression(null, filterType); } } if (string.IsNullOrEmpty(x.Value)) { return null; } LinqExpressionType expressionType = x.DisplayType.GetLinqCondition(); //多个字段or查询 if (x.Fields?.Count > 0) { Expression> express = null; foreach (var field in x.Fields) { PropertyInfo orProperty = TProperties .Where(c => c.Name.Equals(field, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault(); var exp = field.CreateExpression(x.Value, expressionType); if (express == null) { express = exp; } else { express = express.Or(exp); } } return express; } PropertyInfo property = TProperties.Where(c => c.Name.Equals(x.Name, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault(); //字段null处理 if (property == null) return null; //移除查询的值与数据库类型不匹配的数据 object[] values = property.ValidationValueForDbType(x.Value.Split(',')).Where(q => q.Item1).Select(s => s.Item3).ToArray(); if (values == null || values.Length == 0) { return null; } return (LinqExpressionType.In == expressionType || LinqExpressionType.NotIn == expressionType) ? x.Name.CreateExpression(values, expressionType) : x.Name.CreateExpression(x.Value, expressionType); } IQueryable ApplyLegacy(IQueryable q, List list) { //判断列的数据类型数字,日期的需要判断值的格式是否正确 for (int i = 0; i < list.Count; i++) { var expr = BuildExpression(list[i]); if (expr == null) continue; q = q.Where(expr); } return q; } // 如没有分组配置,则完全走原来的 AND 逻辑 bool hasGroup = searchParametersList.Any(x => !string.IsNullOrEmpty(x?.Group)); if (!hasGroup) { return ApplyLegacy(queryable, searchParametersList); } // 1) 先用原逻辑处理“非分组”的条件(保持行为一致) queryable = ApplyLegacy(queryable, searchParametersList.Where(x => string.IsNullOrEmpty(x?.Group)).ToList()); // 2) 分组条件:组内按 JoinType 顺序组合;组与组之间 AND var grouped = searchParametersList .Where(x => !string.IsNullOrEmpty(x?.Group)) .GroupBy(x => x.Group, StringComparer.CurrentCultureIgnoreCase); foreach (var g in grouped) { Expression> groupExpr = null; foreach (var item in g) { var one = BuildExpression(item); if (one == null) continue; groupExpr = groupExpr == null ? one : (item.Or ? groupExpr.Or(one) : groupExpr.And(one)); } if (groupExpr != null) { queryable = queryable.Where(groupExpr); } } return queryable; } private const string _asc = "asc"; /// /// 生成排序字段 /// /// /// public static Dictionary GetPageDataSort( this ServiceBase service, PageDataOptions pageData, PropertyInfo[] propertyInfo = null) where TEntity : BaseEntity where TRepository : IRepository { if (service.OrderByExpression != null) { return service.OrderByExpression.GetExpressionToDic(); } return pageData.GetSort(propertyInfo); } public static Dictionary GetTypeSort(this PageDataOptions pageData) where TEntity : class { return pageData.GetSort(typeof(TEntity).GetProperties()); } public static Dictionary GetSort(this PageDataOptions pageData, PropertyInfo[] propertyInfo = null) { propertyInfo ??= []; if (!string.IsNullOrEmpty(pageData.Sort)) { Dictionary sortDic = new Dictionary(); //多个排序字段{id:asc,date:desc} if (pageData.Sort.Contains('{')) { var dicSort = pageData.Sort.DeserializeObject>(); foreach (var item in dicSort) { sortDic[item.Key] = item.Value?.ToLower() == _asc ? QueryOrderBy.Asc : QueryOrderBy.Desc; } return sortDic; } if (pageData.Sort.Contains(',')) { var sortArr = pageData.Sort.Split(",").Where(x => propertyInfo.Any(c => c.Name == x)).Select(s => s).Distinct().ToList(); foreach (var name in sortArr) { sortDic[name] = pageData.Order?.ToLower() == _asc ? QueryOrderBy.Asc : QueryOrderBy.Desc; } return sortDic; } else if (propertyInfo.Any(x => x.Name == pageData.Sort)) { return new Dictionary() { { pageData.Sort, pageData.Order?.ToLower() == _asc? QueryOrderBy.Asc: QueryOrderBy.Desc } }; } } //如果没有排序字段,则使用主键作为排序字段 PropertyInfo property = propertyInfo.GetKeyProperty(); //如果主键不是自增类型则使用appsettings.json中CreateMember->DateField配置的创建时间作为排序 if (property.PropertyType == typeof(int) || property.PropertyType == typeof(long)) { if (!propertyInfo.Any(x => x.Name.ToLower() == pageData.Sort)) { pageData.Sort = propertyInfo.GetKeyName(); } } else { if (!string.IsNullOrEmpty(AppSetting.CreateMember.DateField) && propertyInfo.Any(x => x.Name == AppSetting.CreateMember.DateField)) { pageData.Sort = AppSetting.CreateMember.DateField; } else { pageData.Sort = propertyInfo.GetKeyName(); } } return new Dictionary() { { pageData.Sort, pageData.Order?.ToLower() == _asc? QueryOrderBy.Asc: QueryOrderBy.Desc } }; } public static ServiceBase InvokeResult( this ServiceBase service, PageGridData gridData) where TEntity : BaseEntity where TRepository : IRepository { service.GetPageDataOnExecuted?.Invoke(gridData); return service; } public static async Task InvokeSummaryExpressAsync( this ServiceBase service, IQueryable queryable) where TEntity : BaseEntity where TRepository : IRepository { if (service.SummaryExpress != null) { return service.InvokeSummaryExpress(queryable); } if (service.SummaryExpressAsync != null) { return await service.SummaryExpressAsync.Invoke(queryable); } return null; } public static object InvokeSummaryExpress( this ServiceBase service, IQueryable queryable) where TEntity : BaseEntity where TRepository : IRepository { if (service.SummaryExpress != null) { return service.SummaryExpress.Invoke(queryable); } return null; } /// /// 映射指定权限的字段不查询数据库 /// /// /// public static List FilterQueryableAuthFields(this IQueryable queryable) where TEntity : class { return queryable.ToList(); } /// /// 字段权限 /// /// /// /// public static Task> FilterQueryableAuthFieldsAsync(this IQueryable queryable) where TEntity : class { return queryable.ToListAsync(); } } }