using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace SqlSugar { public class NavigatManager { public SqlSugarProvider Context { get; set; } public bool IsCrossQueryWithAttr { get; set; } public Dictionary CrossQueryItems { get; set; } public Func, List> SelectR1 { get; set; } public Func, List> SelectR2 { get; set; } public Func, List> SelectR3 { get; set; } public Func, List> SelectR4 { get; set; } public Func, List> SelectR5 { get; set; } public Func, List> SelectR6 { get; set; } public Func, List> SelectR7 { get; set; } public Func, List> SelectR8 { get; set; } public Expression[] Expressions { get; set; } public List RootList { get; set; } public QueryBuilder QueryBuilder { get; set; } //public QueryableProvider Queryable { get; set; } private List _preExpressionList = new List(); private List _preList = new List(); private List _ListCallFunc; //private Expression[] _expressions; //private List _list; //private EntityInfo _entityInfo; public void Execute() { var i = 1; foreach (var item in Expressions) { ExecuteByLay(i, item); i++; } } private void ExecuteByLay(int i, Expression item) { _ListCallFunc = GetWhereExpression(ref item); if (i == 1) { ExecuteByLay(item, RootList.Select(it => it as object).ToList(), SelectR1); } else if (i == 2) { var currentList = RootList; if (RootList == null || currentList.Count == 0) return; var memberExpression = ((_preExpressionList.Last() as LambdaExpression).Body as MemberExpression); var navObjectName = memberExpression.Member.Name; var navType = currentList[0].GetType().GetProperty(navObjectName).PropertyType.Name; var isList = navType.StartsWith("List`"); List list = new List(); if (isList) { list = currentList.SelectMany(it => (it.GetType().GetProperty(navObjectName).GetValue(it) as IList)?.Cast()??new List { }).ToList(); } else { list = currentList.Select(it => (it.GetType().GetProperty(navObjectName).GetValue(it))).ToList(); } ExecuteByLay(item, list, SelectR2); _preList = list; } else if (i == 3) { var currentList = _preList.Where(it => it != null).ToList(); if (RootList == null || currentList.Count == 0) return; List list = ExecuteByLay(currentList); ExecuteByLay(item, list, SelectR3); _preList = list.ToList(); } else if (i == 4) { var currentList = _preList.Where(it => it != null).ToList(); if (RootList == null || currentList.Count == 0) return; List list = ExecuteByLay(currentList); ExecuteByLay(item, list, SelectR4); _preList = list.ToList(); } else if (i == 5) { var currentList = _preList.Where(it => it != null).ToList(); if (RootList == null || currentList.Count == 0) return; List list = ExecuteByLay(currentList); ExecuteByLay(item, list, SelectR5); _preList = list.ToList(); } else if (i == 6) { var currentList = _preList.Where(it => it != null).ToList(); if (RootList == null || currentList.Count == 0) return; List list = ExecuteByLay(currentList); ExecuteByLay(item, list, SelectR6); _preList = list.ToList(); } else if (i == 7) { var currentList = _preList.Where(it => it != null).ToList(); if (RootList == null || currentList.Count == 0) return; List list = ExecuteByLay(currentList); ExecuteByLay(item, list, SelectR7); _preList = list.ToList(); } _preExpressionList.Add(item); _ListCallFunc = new List(); } private List ExecuteByLay(List currentList) { var memberExpression = ((_preExpressionList.Last() as LambdaExpression).Body as MemberExpression); var navObjectName = memberExpression.Member.Name; var navType = currentList[0].GetType().GetProperty(navObjectName).PropertyType.Name; var isList = navType.StartsWith("List`"); List list = new List(); if (isList) { list = currentList.Where(it=> it.GetType().GetProperty(navObjectName).GetValue(it)!=null).SelectMany(it => (it.GetType().GetProperty(navObjectName).GetValue(it) as IList).Cast()).ToList(); } else { list = currentList.Where(it=>it.GetType().GetProperty(navObjectName).GetValue(it)!=null).Select(it => (it.GetType().GetProperty(navObjectName).GetValue(it))).ToList(); } return list; } private void ExecuteByLay(Expression expression, List list, Func, List> selector) { if (list == null || list.Count == 0) return; list = list.Where(it => it != null).ToList(); var memberExpression = ((expression as LambdaExpression).Body as MemberExpression); var listItemType = list.Where(it=>it!=null).FirstOrDefault()?.GetType(); if (listItemType == null) { return; } if (listItemType.Name.StartsWith("List`")) { listItemType = listItemType.GetGenericArguments()[0]; } //if (listItemType == null) return; var listItemEntity = this.Context.EntityMaintenance.GetEntityInfo(listItemType); var listPkColumn = listItemEntity.Columns.Where(it => it.IsPrimarykey).FirstOrDefault(); var navObjectName = memberExpression.Member.Name; var navObjectNamePropety = listItemType.GetProperty(navObjectName); var navObjectNameColumnInfo = listItemEntity.Columns.First(it => it.PropertyName == navObjectName); Check.ExceptionEasy(navObjectNameColumnInfo.Navigat == null, $"{navObjectName} not [Navigat(..)] ", $"{navObjectName} 没有导航特性 [Navigat(..)] "); if (navObjectNameColumnInfo.Navigat.NavigatType == NavigateType.OneToOne) { this.Context.Utilities.PageEach(list, 5000, pageList => { OneToOne(pageList, selector, listItemEntity, navObjectNamePropety, navObjectNameColumnInfo); }); } else if (navObjectNameColumnInfo.Navigat.NavigatType == NavigateType.OneToMany) { this.Context.Utilities.PageEach(list, 5000, pageList => { OneToMany(pageList, selector, listItemEntity, navObjectNamePropety, navObjectNameColumnInfo); }); } else if (navObjectNameColumnInfo.Navigat.NavigatType == NavigateType.ManyToOne) { this.Context.Utilities.PageEach(list, 5000, pageList => { OneToOne(pageList, selector, listItemEntity, navObjectNamePropety, navObjectNameColumnInfo); }); } else if (navObjectNameColumnInfo.Navigat.NavigatType == NavigateType.Dynamic) { this.Context.Utilities.PageEach(list, 100, pageList => { Dynamic(pageList, selector, listItemEntity, navObjectNamePropety, navObjectNameColumnInfo, expression); }); } else { this.Context.Utilities.PageEach(list, 100, pageList => { ManyToMany(pageList, selector, listItemEntity, navObjectNamePropety, navObjectNameColumnInfo); }); } } private List GetWhereExpression(ref Expression expression) { List expressions = new List(); var isCall = (expression as LambdaExpression).Body is MethodCallExpression; if (isCall) { var newexp = (expression as LambdaExpression).Body; while (newexp is MethodCallExpression) { expressions.Add(newexp); newexp= (newexp as MethodCallExpression).Arguments[0]; } expression =LambdaExpression.Lambda(newexp); } return expressions; } private void ManyToMany(List list, Func, List> selector, EntityInfo listItemEntity, System.Reflection.PropertyInfo navObjectNamePropety, EntityColumnInfo navObjectNameColumnInfo) { var bEntity = navObjectNameColumnInfo.PropertyInfo.PropertyType.GetGenericArguments()[0]; var bEntityInfo = this.Context.EntityMaintenance.GetEntityInfo(bEntity); var bPkColumn = bEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); if (navObjectNameColumnInfo.Navigat.BClassId.HasValue()) { bPkColumn= bEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == navObjectNameColumnInfo.Navigat.BClassId); } Check.ExceptionEasy(bPkColumn==null, $"{bEntityInfo.EntityName} need primary key", $"{bEntityInfo.EntityName} 实体需要配置主键"); var bDb = this.Context; bDb = GetCrossDatabase(bDb,bEntity); bDb.InitMappingInfo(bEntity); var listItemPkColumn = listItemEntity.Columns.Where(it => it.IsPrimarykey).FirstOrDefault(); if (navObjectNameColumnInfo.Navigat.AClassId.HasValue()) { listItemPkColumn = listItemEntity.Columns.FirstOrDefault(it => it.PropertyName == navObjectNameColumnInfo.Navigat.AClassId); } Check.ExceptionEasy(listItemPkColumn == null, $"{listItemEntity.EntityName} need primary key", $"{listItemEntity.EntityName} 实体需要配置主键"); var ids = list.Select(it => it.GetType().GetProperty(listItemPkColumn.PropertyName).GetValue(it)).Select(it => it == null ? "null" : it).Distinct().ToList(); var mappingEntity = this.Context.EntityMaintenance.GetEntityInfo(navObjectNameColumnInfo.Navigat.MappingType); var aColumn = mappingEntity.Columns.First(it => it.PropertyName == navObjectNameColumnInfo.Navigat.MappingAId); var bColumn = mappingEntity.Columns.First(it => it.PropertyName == navObjectNameColumnInfo.Navigat.MappingBId); List conditionalModels = new List(); conditionalModels.Add((new ConditionalModel() { ConditionalType = ConditionalType.In, FieldName = aColumn.DbColumnName, FieldValue = String.Join(",", ids), CSharpTypeName = aColumn.PropertyInfo.PropertyType.Name })); var abDb = this.Context; abDb = GetCrossDatabase(abDb, mappingEntity.Type); var queryable = abDb.Queryable(); var abids = queryable.AS(mappingEntity.DbTableName).WhereIF(navObjectNameColumnInfo?.Navigat?.WhereSql!=null, navObjectNameColumnInfo?.Navigat?.WhereSql).ClearFilter(QueryBuilder.RemoveFilters).Filter(this.QueryBuilder?.IsDisabledGobalFilter==true?null:mappingEntity.Type).Where(conditionalModels).Select($"{queryable.SqlBuilder.GetTranslationColumnName(aColumn.DbColumnName)} as aid,{queryable.SqlBuilder.GetTranslationColumnName(bColumn.DbColumnName)} as bid").ToList(); List conditionalModels2 = new List(); conditionalModels2.Add((new ConditionalModel() { ConditionalType = ConditionalType.In, FieldName = bPkColumn.DbColumnName, FieldValue = String.Join(",", abids.Select(it => it.Bid).ToArray()), CSharpTypeName = bColumn.PropertyInfo.PropertyType.Name })); var sql = GetWhereSql(GetCrossDatabase(abDb, bEntity)); if (sql.SelectString == null) { var columns = bEntityInfo.Columns.Where(it => !it.IsIgnore) .Select(it => GetOneToManySelectByColumnInfo(it, abDb)).ToList(); sql.SelectString = String.Join(",", columns); } else { var bid=InstanceFactory.GetQueryBuilderWithContext(abDb).Builder.GetTranslationColumnName(bPkColumn.DbColumnName); if (!sql.SelectString.ToLower().Contains(bid?.ToLower())&&!sql.SelectString.Contains("*")) { sql.SelectString += ("," + bid+" AS " +bid); } } var bList = selector(bDb.Queryable().AS(bEntityInfo.DbTableName).ClearFilter(QueryBuilder.RemoveFilters).Filter(this.QueryBuilder?.IsDisabledGobalFilter == true ? null : bEntityInfo.Type).AddParameters(sql.Parameters).Where(conditionalModels2).WhereIF(sql.WhereString.HasValue(),sql.WhereString).Select(sql.SelectString).OrderByIF(sql.OrderByString.HasValue(),sql.OrderByString)); if (bList.HasValue()) { foreach (var listItem in list) { if (navObjectNamePropety.GetValue(listItem) == null) { var instance = Activator.CreateInstance(navObjectNamePropety.PropertyType, true); var ilist = instance as IList; foreach (var bInfo in bList) { var pk = listItemPkColumn.PropertyInfo.GetValue(listItem).ObjToString(); var bid = bPkColumn.PropertyInfo.GetValue(bInfo).ObjToString(); if (abids.Any(x => x.Aid == pk && x.Bid == bid)) { ilist.Add(bInfo); } } if (sql.MappingExpressions.HasValue()) { MappingFieldsHelper helper = new MappingFieldsHelper(); helper.Context = this.Context; helper.NavEntity = bEntityInfo; helper.RootEntity = this.Context.EntityMaintenance.GetEntityInfo(); helper.SetChildList(navObjectNameColumnInfo, listItem, ilist.Cast().ToList(), sql.MappingExpressions); } else { if (sql.Skip != null || sql.Take != null) { var instanceCast = (instance as IList); var newinstance = Activator.CreateInstance(navObjectNamePropety.PropertyType, true) as IList; SkipTakeIList(sql, instanceCast, newinstance); navObjectNamePropety.SetValue(listItem, newinstance); } else { navObjectNamePropety.SetValue(listItem, instance); } } } } } else { foreach (var listItem in list) { if (navObjectNamePropety.GetValue(listItem) == null) { var newinstance = Activator.CreateInstance(navObjectNamePropety.PropertyType, true) as IList; navObjectNamePropety.SetValue(listItem,newinstance); } } } } private static void SkipTakeIList(SqlInfo sql, IList instanceCast, IList newinstance) { var intArray = Enumerable.Range(0, instanceCast.Count); if (sql.Skip != null) { intArray = intArray .Skip(sql.Skip.Value); } if (sql.Take != null) { intArray = intArray .Take(sql.Take.Value); } foreach (var i in intArray) { newinstance.Add(instanceCast[i]); } } private void OneToOne(List list, Func, List> selector, EntityInfo listItemEntity, System.Reflection.PropertyInfo navObjectNamePropety, EntityColumnInfo navObjectNameColumnInfo) { var navColumn = listItemEntity.Columns.FirstOrDefault(it => it.PropertyName == navObjectNameColumnInfo.Navigat.Name); Check.ExceptionEasy(navColumn == null, "OneToOne navigation configuration error", $"OneToOne导航配置错误: 实体{ listItemEntity.EntityName } 不存在{navObjectNameColumnInfo.Navigat.Name}"); var navType = navObjectNamePropety.PropertyType; var db = this.Context; db = GetCrossDatabase(db,navType); var navEntityInfo = db.EntityMaintenance.GetEntityInfo(navType); db.InitMappingInfo(navEntityInfo.Type); var navPkColumn = navEntityInfo.Columns.Where(it => it.IsPrimarykey).FirstOrDefault(); var navPkCount = navEntityInfo.Columns.Where(it => it.IsPrimarykey).Count(); Check.ExceptionEasy(navPkColumn==null&& navObjectNameColumnInfo.Navigat.Name2==null, navEntityInfo.EntityName+ "need primarykey", navEntityInfo.EntityName + " 需要主键"); if (navObjectNameColumnInfo.Navigat.Name2.HasValue()) { navPkColumn = navEntityInfo.Columns.Where(it => it.PropertyName== navObjectNameColumnInfo.Navigat.Name2).FirstOrDefault(); } if (navPkColumn == null && navType.FullName.IsCollectionsList()) { Check.ExceptionEasy($"{navObjectNamePropety.Name} type error ", $"一对一不能是List对象 {navObjectNamePropety.Name} "); } var ids = list.Select(it => it.GetType().GetProperty(navObjectNameColumnInfo.Navigat.Name).GetValue(it)).Select(it => it == null ? "null" : it).Distinct().ToList(); List conditionalModels = new List(); if (IsEnumNumber(navColumn)) { ids = ids.Select(it => Convert.ToInt64(it)).Cast().ToList(); } if (navPkColumn?.UnderType?.Name == UtilConstants.StringType.Name) { ids = ids.Select(it => it?.ToString()?.Replace(",", "[comma]")).Cast().ToList(); } if (navPkColumn?.UnderType?.Name == UtilConstants.DateType.Name) { ids = ids.Select(it =>it==null?null:it.ObjToDate().ToString("yyyy-MM-dd HH:mm:ss.fff") ).Cast().ToList(); } conditionalModels.Add((new ConditionalModel() { ConditionalType = ConditionalType.In, FieldName = navPkColumn.DbColumnName, FieldValue = String.Join(",", ids), CSharpTypeName = navPkColumn?.UnderType?.Name })); if (OneToOneGlobalInstanceRegistry.IsAny()) { foreach (var item in list) { var firstObj = navObjectNamePropety.GetValue(item); if (OneToOneGlobalInstanceRegistry.IsNavigationInitializerCreated(firstObj)) { navObjectNamePropety.SetValue(item,null); } } } if (list.Any()&&navObjectNamePropety.GetValue(list.First()) == null) { var sqlObj = GetWhereSql(db,navObjectNameColumnInfo.Navigat.Name); if (sqlObj.SelectString == null) { var columns = navEntityInfo.Columns.Where(it => !it.IsIgnore) .Select(it => GetOneToOneSelectByColumnInfo(it,db)).ToList(); sqlObj.SelectString = String.Join(",", columns); } var navList = selector(db.Queryable().ClearFilter(QueryBuilder.RemoveFilters).Filter((navPkColumn.IsPrimarykey&& navPkCount==1) ? null : this.QueryBuilder?.IsDisabledGobalFilter == true ? null : navEntityInfo.Type).AS(GetDbTableName(navEntityInfo,sqlObj)) .WhereIF(navObjectNameColumnInfo.Navigat.WhereSql.HasValue(), navObjectNameColumnInfo.Navigat.WhereSql) .WhereIF(sqlObj.WhereString.HasValue(), sqlObj.WhereString) .AddParameters(sqlObj.Parameters).Where(conditionalModels) .Select(sqlObj.SelectString)); var groupQuery = (from l in list join n in navList on navColumn.PropertyInfo.GetValue(l).ObjToString() equals navPkColumn.PropertyInfo.GetValue(n).ObjToString() select new { l, n }).ToList(); foreach (var item in groupQuery) { // var setValue = navList.FirstOrDefault(x => navPkColumn.PropertyInfo.GetValue(x).ObjToString() == navColumn.PropertyInfo.GetValue(item).ObjToString()); if (navObjectNamePropety.GetValue(item.l) == null) { navObjectNamePropety.SetValue(item.l, item.n); } else { //The reserved } } } } private void OneToMany(List list, Func, List> selector, EntityInfo listItemEntity, System.Reflection.PropertyInfo navObjectNamePropety, EntityColumnInfo navObjectNameColumnInfo) { Check.ExceptionEasy(!navObjectNameColumnInfo.PropertyInfo.PropertyType.GetGenericArguments().Any(), navObjectNamePropety? .Name+ "Navigation configuration error one to many should be List", navObjectNamePropety?.Name+ "导航配置错误一对多应该是List"); var navEntity = navObjectNameColumnInfo.PropertyInfo.PropertyType.GetGenericArguments()[0]; var navEntityInfo = this.Context.EntityMaintenance.GetEntityInfo(navEntity); var childDb = this.Context; childDb = GetCrossDatabase(childDb, navEntityInfo.Type); childDb.InitMappingInfo(navEntityInfo.Type); var navColumn = navEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == navObjectNameColumnInfo.Navigat.Name); Check.ExceptionEasy(navColumn == null, $"{navEntityInfo.EntityName} not found {navObjectNameColumnInfo.Navigat.Name} ", $"实体 {navEntityInfo.EntityName} 未找到导航配置列 {navObjectNameColumnInfo.Navigat.Name} "); //var navType = navObjectNamePropety.PropertyType; var listItemPkColumn = listItemEntity.Columns.Where(it => it.IsPrimarykey).FirstOrDefault(); Check.ExceptionEasy(listItemPkColumn == null&& navObjectNameColumnInfo.Navigat.Name2==null, listItemEntity.EntityName + " not primary key", listItemEntity.EntityName + "没有主键"); if (navObjectNameColumnInfo.Navigat.Name2.HasValue()) { listItemPkColumn = listItemEntity.Columns.Where(it => it.PropertyName== navObjectNameColumnInfo.Navigat.Name2).FirstOrDefault(); Check.ExceptionEasy(listItemPkColumn == null, $"{navObjectNameColumnInfo.PropertyName} Navigate is error ", $"{navObjectNameColumnInfo.PropertyName}导航配置错误,可能顺序反了。"); } var ids = list.Select(it => it.GetType().GetProperty(listItemPkColumn.PropertyName).GetValue(it)).Select(it => it == null ? "null" : it).Distinct().ToList(); List conditionalModels = new List(); if (IsEnumNumber(navColumn)) { ids = ids.Select(it => Convert.ToInt64(it)).Cast().ToList(); } if (navColumn?.UnderType?.Name == UtilConstants.StringType.Name) { ids = ids.Select(it => it?.ToString()?.Replace(",", "[comma]")).Cast().ToList(); } conditionalModels.Add((new ConditionalModel() { ConditionalType = ConditionalType.In, FieldName = navColumn.DbColumnName, FieldValue = String.Join(",", ids), CSharpTypeName = listItemPkColumn?.UnderType?.Name })); var sqlObj = GetWhereSql(childDb,navObjectNameColumnInfo.Navigat.Name); if (list.Any() && navObjectNamePropety.GetValue(list.First()) == null) { if (sqlObj.SelectString == null) { var columns = navEntityInfo.Columns.Where(it => !it.IsIgnore) .Select(it => GetOneToManySelectByColumnInfo(it,childDb)).ToList(); sqlObj.SelectString = String.Join(",", columns); } var navList = selector(childDb.Queryable(sqlObj.TableShortName).AS(GetDbTableName(navEntityInfo, sqlObj)).ClearFilter(QueryBuilder.RemoveFilters).Filter(this.QueryBuilder?.IsDisabledGobalFilter == true ? null : navEntityInfo.Type).AddParameters(sqlObj.Parameters).Where(conditionalModels).WhereIF(sqlObj.WhereString.HasValue(), sqlObj.WhereString).WhereIF(navObjectNameColumnInfo?.Navigat?.WhereSql!=null, navObjectNameColumnInfo?.Navigat?.WhereSql).Select(sqlObj.SelectString).OrderByIF(sqlObj.OrderByString.HasValue(), sqlObj.OrderByString)); if (navList.HasValue()) { //var setValue = navList // .Where(x => navColumn.PropertyInfo.GetValue(x).ObjToString() == listItemPkColumn.PropertyInfo.GetValue(item).ObjToString()).ToList(); var groupQuery = (from l in list.Distinct() join n in navList on listItemPkColumn.PropertyInfo.GetValue(l).ObjToString() equals navColumn.PropertyInfo.GetValue(n).ObjToString() select new { l, n }).GroupBy(it => it.l).ToList(); foreach (var item in groupQuery) { var itemSelectList=item.Select(it => it.n); if (sqlObj.Skip != null) { itemSelectList = itemSelectList .Skip(sqlObj.Skip.Value); } if (sqlObj.Take != null) { itemSelectList = itemSelectList .Take(sqlObj.Take.Value); } if (sqlObj.MappingExpressions.HasValue()) { MappingFieldsHelper helper = new MappingFieldsHelper(); helper.NavEntity = navEntityInfo; helper.Context = this.Context; helper.RootEntity = this.Context.EntityMaintenance.GetEntityInfo(); helper.SetChildList(navObjectNameColumnInfo, item.Key, itemSelectList.ToList(), sqlObj.MappingExpressions); } else { var instance = Activator.CreateInstance(navObjectNamePropety.PropertyType, true); var ilist = instance as IList; foreach (var value in itemSelectList.ToList()) { ilist.Add(value); } navObjectNamePropety.SetValue(item.Key, instance); } } foreach (var item in list) { if (navObjectNamePropety.GetValue(item) == null) { var instance = Activator.CreateInstance(navObjectNamePropety.PropertyType, true); navObjectNamePropety.SetValue(item, instance); } } } else { //No navigation data set new List() foreach (var item in list) { var instance = Activator.CreateInstance(navObjectNamePropety.PropertyType, true); navObjectNamePropety.SetValue(item, instance); } } } } private void Dynamic(List list, Func, List> selector, EntityInfo listItemEntity, System.Reflection.PropertyInfo navObjectNamePropety, EntityColumnInfo navObjectNameColumnInfo,Expression expression) { var args = navObjectNameColumnInfo.PropertyInfo.PropertyType.GetGenericArguments(); if (args.Length == 0) { DynamicOneToOne(list,selector,listItemEntity, navObjectNamePropety, navObjectNameColumnInfo,expression); return; } var navEntity = args[0]; var childDb = this.Context; childDb = GetCrossDatabase(childDb, navEntity); childDb.InitMappingInfo(navEntity); var navEntityInfo = childDb.EntityMaintenance.GetEntityInfo(navEntity); var sqlObj = GetWhereSql(childDb,navObjectNameColumnInfo.Navigat.Name); if (IsJsonMapping(navObjectNameColumnInfo, sqlObj)) { CreateDynamicMappingExpression(sqlObj, navObjectNameColumnInfo.Navigat.Name, navEntityInfo, listItemEntity); if (sqlObj.WhereString == null) { sqlObj.WhereString = navObjectNameColumnInfo?.Navigat?.Name2; } } Check.ExceptionEasy(sqlObj.MappingExpressions.IsNullOrEmpty(), $"{expression} error,dynamic need MappingField ,Demo: Includes(it => it.Books.MappingField(z=>z.studenId,()=>it.StudentId).ToList())", $"{expression} 解析出错,自定义映射需要 MappingField ,例子: Includes(it => it.Books.MappingField(z=>z.studenId,()=>it.StudentId).ToList())"); if (list.Any() && navObjectNamePropety.GetValue(list.First()) == null) { MappingFieldsHelper helper = new MappingFieldsHelper(); helper.Context = childDb; helper.NavEntity = navEntityInfo; helper.RootEntity = childDb.EntityMaintenance.GetEntityInfo(); var whereSql = helper.GetMppingSql(list, sqlObj.MappingExpressions); var navList = selector(childDb.Queryable().AS(GetDbTableName(navEntityInfo, sqlObj)).AddParameters(sqlObj.Parameters).Where(whereSql,true).WhereIF(sqlObj.WhereString.HasValue(), sqlObj.WhereString).Select(sqlObj.SelectString).OrderByIF(sqlObj.OrderByString.HasValue(), sqlObj.OrderByString)); if (navList.HasValue()) { foreach (var item in list) { helper.SetChildList(navObjectNameColumnInfo, item, navList, sqlObj.MappingExpressions); } } } } private void DynamicOneToOne(List list, Func, List> selector, EntityInfo listItemEntity, System.Reflection.PropertyInfo navObjectNamePropety, EntityColumnInfo navObjectNameColumnInfo,Expression expression) { var navEntity = navObjectNameColumnInfo.PropertyInfo.PropertyType; var navEntityInfo = this.Context.EntityMaintenance.GetEntityInfo(navEntity); var childDb = this.Context; childDb = GetCrossDatabase(childDb, navEntity); this.Context.InitMappingInfo(navEntity); var sqlObj = GetWhereSql(childDb,navObjectNameColumnInfo.Navigat.Name); if (IsJsonMapping(navObjectNameColumnInfo, sqlObj)) { CreateDynamicMappingExpression(sqlObj, navObjectNameColumnInfo.Navigat.Name, navEntityInfo, listItemEntity); if (sqlObj.WhereString == null) { sqlObj.WhereString = navObjectNameColumnInfo?.Navigat?.Name2; } } Check.ExceptionEasy(sqlObj.MappingExpressions.IsNullOrEmpty(), $"{expression} error,dynamic need MappingField ,Demo: Includes(it => it.Books.MappingField(z=>z.studenId,()=>it.StudentId).ToList())", $"{expression}解析出错, 自定义映射需要 MappingField ,例子: Includes(it => it.Books.MappingField(z=>z.studenId,()=>it.StudentId).ToList())"); if (list.Any() && navObjectNamePropety.GetValue(list.First()) == null) { MappingFieldsHelper helper = new MappingFieldsHelper(); helper.Context = this.Context; helper.NavEntity = navEntityInfo; helper.RootEntity = this.Context.EntityMaintenance.GetEntityInfo(); var whereSql = helper.GetMppingSql(list, sqlObj.MappingExpressions); var navList = selector(childDb.Queryable().AS(GetDbTableName(navEntityInfo, sqlObj)).AddParameters(sqlObj.Parameters).Where(whereSql, true).WhereIF(sqlObj.WhereString.HasValue(), sqlObj.WhereString).Select(sqlObj.SelectString).OrderByIF(sqlObj.OrderByString.HasValue(), sqlObj.OrderByString)); if (navList.HasValue()) { foreach (var item in list) { helper.SetChildItem(navObjectNameColumnInfo, item, navList, sqlObj.MappingExpressions); } } } } private SqlInfo GetWhereSql(ISqlSugarClient db,string properyName=null) { if (_ListCallFunc == null|| _ListCallFunc.Count==0) return new SqlInfo(); List where = new List(); List oredrBy = new List(); _ListCallFunc.Reverse(); SqlInfo result = new SqlInfo(); result.Parameters = new List(); var isList = false; int parameterIndex = 100; foreach (var item in _ListCallFunc) { var method = item as MethodCallExpression; var queryable = db.Queryable(); if (method.Method.Name == "Where") { if (method.Arguments[1].Type == typeof(List)) { //var x=method.Arguments[1]; var conditionals = ExpressionTool.GetExpressionValue(method.Arguments[1]) as List; if (conditionals.Count > 0) { var whereObj = queryable.QueryBuilder.Builder.ConditionalModelToSql(conditionals); where.Add(whereObj.Key); if(whereObj.Value!=null) result.Parameters.AddRange(whereObj.Value); } } else { queryable.QueryBuilder.LambdaExpressions.ParameterIndex = parameterIndex; CheckHasRootShortName(method.Arguments[0], method.Arguments[1]); var exp = method.Arguments[1]; InitMappingtType(exp); where.Add(" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.WhereSingle).GetString()); SetTableShortName(result, queryable); parameterIndex=queryable.QueryBuilder.LambdaExpressions.ParameterIndex ; } } else if (method.Method.Name == "WhereIF") { var isOk = LambdaExpression.Lambda(method.Arguments[1]).Compile().DynamicInvoke(); if (isOk.ObjToBool()) { queryable.QueryBuilder.LambdaExpressions.ParameterIndex = parameterIndex; var exp = method.Arguments[2]; InitMappingtType(exp); CheckHasRootShortName(method.Arguments[1], method.Arguments[2]); where.Add(" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.WhereSingle).GetString()); SetTableShortName(result, queryable); parameterIndex = queryable.QueryBuilder.LambdaExpressions.ParameterIndex; } } else if (method.Method.Name.IsIn( "OrderBy", "ThenBy")) { var exp = method.Arguments[1]; oredrBy.Add(" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.WhereSingle).GetString()); SetTableShortName(result, queryable); } else if (method.Method.Name == "MappingField") { if (result.MappingExpressions == null) result.MappingExpressions = new List(); result.MappingExpressions.Add(new MappingFieldsExpression() { LeftColumnExpression = method.Arguments[1], RightColumnExpression = method.Arguments[2] }); } else if (method.Method.Name == "Select") { Select(properyName, result, method, queryable); } else if (method.Method.Name.IsIn("OrderByDescending", "ThenByDescending")) { var exp = method.Arguments[1]; oredrBy.Add(" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.WhereSingle).GetString() + " DESC"); } else if (method.Method.Name == "Skip") { var exp = method.Arguments[1]; if (exp is BinaryExpression) { result.Skip = (int)ExpressionTool.DynamicInvoke(exp); } else { result.Skip = (int)ExpressionTool.GetExpressionValue(exp); } } else if (method.Method.Name == "Take") { var exp = method.Arguments[1]; if (exp is BinaryExpression) { result.Take = (int)ExpressionTool.DynamicInvoke(exp); } else { result.Take = (int)ExpressionTool.GetExpressionValue(exp); } } else if (method.Method.Name == "ToList") { if (method.Arguments.Count > 1) { Select(properyName, result, method, queryable); } isList = true; } else if (method.Method.Name == "SplitTable") { var exp =(Expression, IEnumerable>>) (item as MethodCallExpression).Arguments[1]; result.SplitTable = exp.Compile(); } else { Check.ExceptionEasy($"no support {item}", $"不支持表达式{item} 不支持方法{method.Method.Name}"); } if(queryable.QueryBuilder.Parameters!=null) result.Parameters.AddRange(queryable.QueryBuilder.Parameters); } if (where.Any()) { Check.ExceptionEasy(isList == false, $"{_ListCallFunc.First()} need is ToList()", $"{_ListCallFunc.First()} 需要ToList"); result.WhereString= String.Join(" AND ", where); } if (oredrBy.Any()) { Check.ExceptionEasy(isList == false, $"{_ListCallFunc.First()} need is ToList()", $"{_ListCallFunc.First()} 需要ToList"); result.OrderByString = String.Join(" , ", oredrBy); } if (result.SelectString.HasValue()) { Check.ExceptionEasy(isList == false, $"{_ListCallFunc.First()} need is ToList()", $"{_ListCallFunc.First()} 需要ToList"); result.OrderByString = String.Join(" , ", oredrBy); } return result; } private void Select(string properyName, SqlInfo result, MethodCallExpression method, ISugarQueryable queryable) { var exp = method.Arguments[1]; var newExp = (exp as LambdaExpression).Body; var types = exp.Type.GetGenericArguments(); var ps=ExpressionTool.GetParameters(exp).Select(it=>it.Name).Distinct().ToList(); if (ps.Count > 1 && result.TableShortName.IsNullOrEmpty()) { result.TableShortName = ps[0]; } if (types != null && types.Length > 0) { var type = types[0]; var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(type); this.Context.InitMappingInfo(type); Check.ExceptionEasy(newExp.Type != entityInfo.Type, $" new {newExp.Type.Name}is error ,use Select(it=>new {entityInfo.Type.Name})", $"new {newExp.Type.Name}是错误的,请使用Select(it=>new {entityInfo.Type.Name})"); if (entityInfo.Columns.Count(x => x.Navigat != null) == 0) { result.SelectString = (" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.SelectSingle).GetString()); } else { var pkInfo = entityInfo.Columns.FirstOrDefault(x => x.IsPrimarykey); result.SelectString = (" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.SelectSingle).GetString()); if (pkInfo != null) { var pkName = pkInfo.DbColumnName; AppColumns(result, queryable, pkName); } foreach (var nav in entityInfo.Columns.Where(x => x.Navigat != null && x.Navigat.NavigatType == NavigateType.OneToOne)) { var navColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyName == nav.Navigat.Name); if (navColumn != null) { AppColumns(result, queryable, navColumn.DbColumnName); } } foreach (var nav in entityInfo.Columns.Where(x => x.Navigat != null && x.Navigat.NavigatType == NavigateType.OneToMany && x.Navigat.Name2 != null)) { var navColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyName == nav.Navigat.Name2); if (navColumn != null) { AppColumns(result, queryable, navColumn.DbColumnName); } } result.SelectString = result.SelectString.TrimStart(','); if (result.SelectString == "") { result.SelectString = null; } } if (properyName != null) { var fkColumnsInfo = entityInfo.Columns.FirstOrDefault(x => x.PropertyName == properyName); var pkColumnsInfo = entityInfo.Columns.FirstOrDefault(x => x.IsPrimarykey); if (fkColumnsInfo != null) { var fkName = fkColumnsInfo.DbColumnName; AppColumns(result, queryable, fkName); } if (pkColumnsInfo!=null&&fkColumnsInfo == null&&result.SelectString != null && !result.SelectString.Contains(queryable.SqlBuilder.GetTranslationColumnName(pkColumnsInfo.DbColumnName))) { AppColumns(result, queryable, pkColumnsInfo.DbColumnName); } } } } private static void SetTableShortName(SqlInfo result, ISugarQueryable queryable) { if (queryable.QueryBuilder.TableShortName.HasValue()&& result.TableShortName.IsNullOrEmpty()) { result.TableShortName = queryable.QueryBuilder.TableShortName; } } private SqlSugarProvider GetCrossDatabase(SqlSugarProvider db, Type type) { if (IsCrossQueryWithAttr == false && this.CrossQueryItems == null) { return db; } else if (IsCrossQueryWithAttr) { var tenant = type.GetCustomAttribute(); if (tenant != null) { return db.Root.GetConnection(tenant.configId); } else { return db; } } else if (this.CrossQueryItems!=null&& this.CrossQueryItems.Count>0&&this.CrossQueryItems.ContainsKey(type.FullName)) { var result= db.Root.GetConnection(this.CrossQueryItems[type.FullName]); return result; } else { return db; } } private static void AppColumns(SqlInfo result, ISugarQueryable queryable, string columnName) { var selectPkName = queryable.SqlBuilder.GetTranslationColumnName(columnName); if (result.SelectString!=null && !result.SelectString.ToLower().Contains(selectPkName.ToLower())) { result.SelectString = result.SelectString + "," + (selectPkName +" AS "+ selectPkName); } } public void CheckHasRootShortName(Expression rootExpression, Expression childExpression) { var rootShortName = GetShortName(rootExpression); if (rootShortName.HasValue()&& childExpression.ToString().Contains($" {rootShortName}.")) { Check.ExceptionEasy($".Where({childExpression}) no support {rootShortName}.Field, Use .MappingField",$".Where({childExpression})禁止出{rootShortName}.字段 , 你可以使用.MappingField(z=>z.字段,()=>{rootShortName}.字段) 与主表字段进行过滤"); } else if (rootShortName.HasValue() && childExpression.ToString().Contains($"({rootShortName}.")) { Check.ExceptionEasy($".Where({childExpression}) no support {rootShortName}.Field, Use .MappingField", $".Where({childExpression})禁止出{rootShortName}.字段 , 你可以使用.MappingField(z=>z.字段,()=>{rootShortName}.字段) 与主表字段进行过滤"); } } private static string GetShortName(Expression expression1) { string shortName = null; if (expression1 is MemberExpression) { var shortNameExpression = (expression1 as MemberExpression).Expression; if (shortNameExpression != null && shortNameExpression.Type == typeof(T)) { if (shortNameExpression is ParameterExpression) { shortName = (shortNameExpression as ParameterExpression).Name; } } } return shortName; } private string GetDbTableName(EntityInfo navEntityInfo,SqlInfo sqlInfo) { if (navEntityInfo.Type.GetCustomAttribute() != null&&sqlInfo.SplitTable!=null) { return "(" + this.Context.QueryableByObject(navEntityInfo.Type).SplitTable(sqlInfo.SplitTable).ToSqlString() + ") split_table"; } else if (navEntityInfo.Type.GetCustomAttribute() != null) { return "("+this.Context.QueryableByObject(navEntityInfo.Type).SplitTable().ToSqlString()+") split_table"; } else { return navEntityInfo.DbTableName; } } private void InitMappingtType(Expression exp) { if (exp is LambdaExpression) { var pars = (exp as LambdaExpression).Parameters; if (pars != null) { foreach (var item in pars) { this.Context.InitMappingInfo(item.Type); } } } } private bool IsEnumNumber(EntityColumnInfo navPkColumn) { return navPkColumn?.UnderType?.IsEnum()==true && navPkColumn?.SqlParameterDbType == null && this.Context?.CurrentConnectionConfig?.MoreSettings?.TableEnumIsString != true; } private static bool IsJsonMapping(EntityColumnInfo navObjectNameColumnInfo, SqlInfo sqlObj) { return sqlObj.MappingExpressions == null && navObjectNameColumnInfo.Navigat.Name.HasValue(); } private void CreateDynamicMappingExpression(SqlInfo sqlObj, string name, EntityInfo navEntityInfo, EntityInfo listItemEntity) { var json = Newtonsoft.Json.Linq.JArray.Parse(name); sqlObj.MappingExpressions = new List(); foreach (var item in json) { string m = item["m"]+""; string c = item["c"] + ""; Check.ExceptionEasy(m.IsNullOrEmpty() || c.IsNullOrEmpty(), $"{name} Navigation json format error, see documentation", $"{name}导航json格式错误,请看文档"); var cColumn= navEntityInfo.Columns.FirstOrDefault(it => it.PropertyName.EqualCase(c)); Check.ExceptionEasy(cColumn==null, $"{c} does not exist in {navEntityInfo.EntityName}", $"{c}不存在于{navEntityInfo.EntityName}"); var mColumn = listItemEntity.Columns.FirstOrDefault(it => it.PropertyName.EqualCase(m)); Check.ExceptionEasy(cColumn == null, $"{m} does not exist in {listItemEntity.EntityName}", $"{m}不存在于{listItemEntity.EntityName}"); sqlObj.MappingExpressions.Add(new MappingFieldsExpression() { LeftEntityColumn = cColumn, RightEntityColumn = mColumn, }); } } private string GetOneToManySelectByColumnInfo(EntityColumnInfo it,ISqlSugarClient db) { QueryBuilder QueryBuilder =InstanceFactory.GetQueryBuilderWithContext(db); if (it.QuerySql.HasValue()) { return it.QuerySql + " AS " + QueryBuilder.Builder.GetTranslationColumnName(it.PropertyName); } return QueryBuilder.Builder.GetTranslationColumnName(it.DbColumnName) + " AS " + QueryBuilder.Builder.GetTranslationColumnName(it.PropertyName); } private string GetOneToOneSelectByColumnInfo(EntityColumnInfo it,ISqlSugarClient db) { QueryBuilder QueryBuilder = InstanceFactory.GetQueryBuilderWithContext(db); if (it.QuerySql.HasValue()) { return it.QuerySql + " AS " + QueryBuilder.Builder.GetTranslationColumnName(it.PropertyName); } return QueryBuilder.Builder.GetTranslationColumnName(it.DbColumnName) + " AS " + QueryBuilder.Builder.GetTranslationColumnName(it.PropertyName); } } }