sqlsugar/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs

1012 lines
53 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<T>
{
public SqlSugarProvider Context { get; set; }
public bool IsCrossQueryWithAttr { get; set; }
public Dictionary<string, string> CrossQueryItems { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR1 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR2 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR3 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR4 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR5 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR6 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR7 { get; set; }
public Func<ISugarQueryable<object>, List<object>> SelectR8 { get; set; }
public Expression[] Expressions { get; set; }
public List<T> RootList { get; set; }
public QueryBuilder QueryBuilder { get; set; }
//public QueryableProvider<T> Queryable { get; set; }
private List<Expression> _preExpressionList = new List<Expression>();
private List<object> _preList = new List<object>();
private List<Expression> _ListCallFunc;
//private Expression[] _expressions;
//private List<T> _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<object> list = new List<object>();
if (isList)
{
list = currentList.SelectMany(it => (it.GetType().GetProperty(navObjectName).GetValue(it) as IList)?.Cast<object>()??new List<object> { }).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<object> 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<object> 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<object> 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<object> 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<object> list = ExecuteByLay(currentList);
ExecuteByLay(item, list, SelectR7);
_preList = list.ToList();
}
_preExpressionList.Add(item);
_ListCallFunc = new List<Expression>();
}
private List<object> ExecuteByLay(List<object> 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<object> list = new List<object>();
if (isList)
{
list = currentList.Where(it=> it.GetType().GetProperty(navObjectName).GetValue(it)!=null).SelectMany(it => (it.GetType().GetProperty(navObjectName).GetValue(it) as IList).Cast<object>()).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<object> list, Func<ISugarQueryable<object>, List<object>> 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<Expression> GetWhereExpression(ref Expression expression)
{
List<Expression> expressions = new List<Expression>();
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<object> list, Func<ISugarQueryable<object>, List<object>> 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<IConditionalModel> conditionalModels = new List<IConditionalModel>();
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<object>();
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<SugarAbMapping>($"{queryable.SqlBuilder.GetTranslationColumnName(aColumn.DbColumnName)} as aid,{queryable.SqlBuilder.GetTranslationColumnName(bColumn.DbColumnName)} as bid").ToList();
List<IConditionalModel> conditionalModels2 = new List<IConditionalModel>();
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<object>().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<T> helper = new MappingFieldsHelper<T>();
helper.Context = this.Context;
helper.NavEntity = bEntityInfo;
helper.RootEntity = this.Context.EntityMaintenance.GetEntityInfo<T>();
helper.SetChildList(navObjectNameColumnInfo, listItem, ilist.Cast<object>().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<object> list, Func<ISugarQueryable<object>, List<object>> 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<IConditionalModel> conditionalModels = new List<IConditionalModel>();
if (IsEnumNumber(navColumn))
{
ids = ids.Select(it => Convert.ToInt64(it)).Cast<object>().ToList();
}
if (navPkColumn?.UnderType?.Name == UtilConstants.StringType.Name)
{
ids = ids.Select(it => it?.ToString()?.Replace(",", "[comma]")).Cast<object>().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<object>().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<object>().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<object> list, Func<ISugarQueryable<object>, List<object>> 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<T>", navObjectNamePropety?.Name+ "导航配置错误一对多应该是List<T>");
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<IConditionalModel> conditionalModels = new List<IConditionalModel>();
if (IsEnumNumber(navColumn))
{
ids = ids.Select(it => Convert.ToInt64(it)).Cast<object>().ToList();
}
if (navColumn?.UnderType?.Name == UtilConstants.StringType.Name)
{
ids = ids.Select(it => it?.ToString()?.Replace(",", "[comma]")).Cast<object>().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<object>(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<T> helper = new MappingFieldsHelper<T>();
helper.NavEntity = navEntityInfo;
helper.Context = this.Context;
helper.RootEntity = this.Context.EntityMaintenance.GetEntityInfo<T>();
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<object> list, Func<ISugarQueryable<object>, List<object>> 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<T> helper = new MappingFieldsHelper<T>();
helper.Context = childDb;
helper.NavEntity = navEntityInfo;
helper.RootEntity = childDb.EntityMaintenance.GetEntityInfo<T>();
var whereSql = helper.GetMppingSql(list, sqlObj.MappingExpressions);
var navList = selector(childDb.Queryable<object>().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<object> list, Func<ISugarQueryable<object>, List<object>> 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} errordynamic 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<T> helper = new MappingFieldsHelper<T>();
helper.Context = this.Context;
helper.NavEntity = navEntityInfo;
helper.RootEntity = this.Context.EntityMaintenance.GetEntityInfo<T>();
var whereSql = helper.GetMppingSql(list, sqlObj.MappingExpressions);
var navList = selector(childDb.Queryable<object>().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<string> where = new List<string>();
List<string> oredrBy = new List<string>();
_ListCallFunc.Reverse();
SqlInfo result = new SqlInfo();
result.Parameters = new List<SugarParameter>();
var isList = false;
int parameterIndex = 100;
foreach (var item in _ListCallFunc)
{
var method = item as MethodCallExpression;
var queryable = db.Queryable<object>();
if (method.Method.Name == "Where")
{
if (method.Arguments[1].Type == typeof(List<IConditionalModel>))
{
//var x=method.Arguments[1];
var conditionals = ExpressionTool.GetExpressionValue(method.Arguments[1]) as List<IConditionalModel>;
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<MappingFieldsExpression>();
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<Func<List<SplitTableInfo>, IEnumerable<SplitTableInfo>>>) (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<object> 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<object> 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<TenantAttribute>();
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<object> 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<SplitTableAttribute>() != null&&sqlInfo.SplitTable!=null)
{
return "(" + this.Context.QueryableByObject(navEntityInfo.Type).SplitTable(sqlInfo.SplitTable).ToSqlString() + ") split_table";
}
else if (navEntityInfo.Type.GetCustomAttribute<SplitTableAttribute>() != 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<MappingFieldsExpression>();
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);
}
}
}