From 01950b556cf7d5affbdd7231ac10378e24cc858e Mon Sep 17 00:00:00 2001 From: sunkaixuan <610262374@qq.com> Date: Tue, 3 May 2022 14:44:59 +0800 Subject: [PATCH] Update Core --- .../QueryableProvider/MappingFieldsHelper.cs | 107 +++++----- .../QueryableProvider/QueryableProvider.cs | 101 +++++++++- .../Common/ExpressionItems.cs | 34 ++++ .../ResolveItems/MapperExpressionResolve.cs | 4 +- .../ResolveItems/MemberExpressionResolve.cs | 14 ++ .../MethodCallExpressionResolve.cs | 9 + .../OneToManyNavgateExpressionN.cs | 187 ++++++++++++++++++ .../OneToOneNavgateExpressionN.cs | 142 +++++++++++++ .../SqlSugar/Interface/IQueryable.cs | 2 + 9 files changed, 545 insertions(+), 55 deletions(-) create mode 100644 Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs create mode 100644 Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs create mode 100644 Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToOneNavgateExpressionN.cs diff --git a/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/MappingFieldsHelper.cs b/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/MappingFieldsHelper.cs index fafee5c00..3e6f7ba01 100644 --- a/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/MappingFieldsHelper.cs +++ b/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/MappingFieldsHelper.cs @@ -57,57 +57,10 @@ namespace SqlSugar public void SetChildList(EntityColumnInfo navColumnInfo,object item,List list, List mappingFieldsExpressions) { - if (item != null) + if (item != null) { //var expable =Expressionable.Create(); - foreach (var field in mappingFieldsExpressions) - { - InitMappingFieldsExpression(field); - } - var setList =new List(); - var count = mappingFieldsExpressions.Count; - if (count == 1) - { - setList=list.Where(it => GetWhereByIndex(item, mappingFieldsExpressions, it, 0)).ToList(); - } - else if (count == 2) - { - setList = list.Where(it => - GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 1) - ).ToList(); - } - else if (count == 3) - { - setList = list.Where(it => - GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 1) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 2) - ).ToList(); - } - else if (count == 4) - { - setList = list.Where(it => - GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 1) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 2) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 3) - ).ToList(); - } - else if (count == 5) - { - setList = list.Where(it => - GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 1) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 2) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 3) && - GetWhereByIndex(item, mappingFieldsExpressions, it, 4) - ).ToList(); - } - else - { - Check.ExceptionEasy("MappingField max value is 5", "MappingField最大数量不能超过5"); - } + List setList = GetSetList(item, list, mappingFieldsExpressions); //navColumnInfo.PropertyInfo.SetValue(); var instance = Activator.CreateInstance(navColumnInfo.PropertyInfo.PropertyType, true); var ilist = instance as IList; @@ -115,10 +68,64 @@ namespace SqlSugar { ilist.Add(value); } - navColumnInfo.PropertyInfo.SetValue(item,ilist); + navColumnInfo.PropertyInfo.SetValue(item, ilist); } } + public List GetSetList(object item, List list, List mappingFieldsExpressions) + { + foreach (var field in mappingFieldsExpressions) + { + InitMappingFieldsExpression(field); + } + var setList = new List(); + var count = mappingFieldsExpressions.Count; + if (count == 1) + { + setList = list.Where(it => GetWhereByIndex(item, mappingFieldsExpressions, it, 0)).ToList(); + } + else if (count == 2) + { + setList = list.Where(it => + GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 1) + ).ToList(); + } + else if (count == 3) + { + setList = list.Where(it => + GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 1) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 2) + ).ToList(); + } + else if (count == 4) + { + setList = list.Where(it => + GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 1) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 2) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 3) + ).ToList(); + } + else if (count == 5) + { + setList = list.Where(it => + GetWhereByIndex(item, mappingFieldsExpressions, it, 0) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 1) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 2) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 3) && + GetWhereByIndex(item, mappingFieldsExpressions, it, 4) + ).ToList(); + } + else + { + Check.ExceptionEasy("MappingField max value is 5", "MappingField最大数量不能超过5"); + } + + return setList; + } + private static bool GetWhereByIndex(object item, List mappingFieldsExpressions, object it,int index) { var left = mappingFieldsExpressions[index].LeftEntityColumn.PropertyInfo.GetValue(it).ObjToString(); diff --git a/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs b/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs index a8e0c85ef..e2ce038a5 100644 --- a/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs +++ b/Src/Asp.NetCore2/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs @@ -1386,7 +1386,7 @@ namespace SqlSugar { pkName = ((mappingFiled as LambdaExpression).Body as MemberExpression).Member.Name; } - var key = thisFiled.ToString() +typeof(ParameterT).FullName + typeof(T).FullName; + var key = thisFiled.ToString()+mappingFiled.ToString() +typeof(ParameterT).FullName + typeof(T).FullName; var ids = list.Where(it=>it!=null).Select(it => it.GetType().GetProperty(pkName).GetValue(it)).Distinct().ToArray(); if (queryableContext.TempChildLists == null) queryableContext.TempChildLists = new Dictionary(); @@ -1417,7 +1417,54 @@ namespace SqlSugar result = result.Where(it => it.GetType().GetProperty(name).GetValue(it).ObjToString() == pkValue.ObjToString()).ToList(); return result; } - + public List SetContext(Expression> thisFiled1, Expression> mappingFiled1, + Expression> thisFiled2, Expression> mappingFiled2, + ParameterT parameter) + { + if (parameter == null) + { + return new List(); + } + var rightEntity = this.Context.EntityMaintenance.GetEntityInfo(); + var leftEntity = this.Context.EntityMaintenance.GetEntityInfo(); + List result = new List(); + var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext; + var list = queryableContext.list; + var key = thisFiled1.ToString() + mappingFiled1.ToString()+ + thisFiled2.ToString() + mappingFiled2.ToString()+ + typeof(ParameterT).FullName + typeof(T).FullName; + MappingFieldsHelper fieldsHelper = new MappingFieldsHelper(); + var mappings = new List() { + new MappingFieldsExpression(){ + LeftColumnExpression=thisFiled1, + LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled1)), + RightColumnExpression=mappingFiled1, + RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled1)) + }, + new MappingFieldsExpression(){ + LeftColumnExpression=thisFiled2, + LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled2)), + RightColumnExpression=mappingFiled2, + RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled2)) + } + }; + var conditionals=fieldsHelper.GetMppingSql(list, mappings); + if (queryableContext.TempChildLists == null) + queryableContext.TempChildLists = new Dictionary(); + if (list != null && queryableContext.TempChildLists.ContainsKey(key)) + { + result = (List)queryableContext.TempChildLists[key]; + } + else + { + result = this.Clone().Where(conditionals,true).ToList(); + queryableContext.TempChildLists[key] = result; + } + List listObj = result.Select(it => (object)it).ToList(); + object obj = (object)parameter; + var newResult = fieldsHelper.GetSetList(obj, listObj, mappings).Select(it=>(T)it ).ToList(); + return newResult; + } public async Task> SetContextAsync(Expression> thisFiled, Expression> mappingFiled, ParameterT parameter) { List result = new List(); @@ -1433,7 +1480,7 @@ namespace SqlSugar { pkName = ((mappingFiled as LambdaExpression).Body as MemberExpression).Member.Name; } - var key = thisFiled.ToString() + typeof(ParameterT).FullName + typeof(T).FullName; + var key = thisFiled.ToString()+ mappingFiled.ToString() + typeof(ParameterT).FullName + typeof(T).FullName; var ids = list.Select(it => it.GetType().GetProperty(pkName).GetValue(it)).ToArray(); if (queryableContext.TempChildLists == null) queryableContext.TempChildLists = new Dictionary(); @@ -1464,6 +1511,54 @@ namespace SqlSugar result = result.Where(it => it.GetType().GetProperty(name).GetValue(it).ObjToString() == pkValue.ObjToString()).ToList(); return result; } + public async Task> SetContextAsync(Expression> thisFiled1, Expression> mappingFiled1, + Expression> thisFiled2, Expression> mappingFiled2, + ParameterT parameter) + { + if (parameter == null) + { + return new List(); + } + var rightEntity = this.Context.EntityMaintenance.GetEntityInfo(); + var leftEntity = this.Context.EntityMaintenance.GetEntityInfo(); + List result = new List(); + var queryableContext = this.Context.TempItems["Queryable_To_Context"] as MapperContext; + var list = queryableContext.list; + var key = thisFiled1.ToString() + mappingFiled1.ToString() + + thisFiled2.ToString() + mappingFiled2.ToString() + + typeof(ParameterT).FullName + typeof(T).FullName; + MappingFieldsHelper fieldsHelper = new MappingFieldsHelper(); + var mappings = new List() { + new MappingFieldsExpression(){ + LeftColumnExpression=thisFiled1, + LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled1)), + RightColumnExpression=mappingFiled1, + RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled1)) + }, + new MappingFieldsExpression(){ + LeftColumnExpression=thisFiled2, + LeftEntityColumn=leftEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(thisFiled2)), + RightColumnExpression=mappingFiled2, + RightEntityColumn=rightEntity.Columns.First(it=>it.PropertyName==ExpressionTool.GetMemberName(mappingFiled2)) + } + }; + var conditionals = fieldsHelper.GetMppingSql(list, mappings); + if (queryableContext.TempChildLists == null) + queryableContext.TempChildLists = new Dictionary(); + if (list != null && queryableContext.TempChildLists.ContainsKey(key)) + { + result = (List)queryableContext.TempChildLists[key]; + } + else + { + result =await this.Clone().Where(conditionals, true).ToListAsync(); + queryableContext.TempChildLists[key] = result; + } + List listObj = result.Select(it => (object)it).ToList(); + object obj = (object)parameter; + var newResult = fieldsHelper.GetSetList(obj, listObj, mappings).Select(it => (T)it).ToList(); + return newResult; + } public virtual void ForEach(Action action, int singleMaxReads = 300,System.Threading.CancellationTokenSource cancellationTokenSource = null) { Check.Exception(this.QueryBuilder.Skip > 0 || this.QueryBuilder.Take > 0, ErrorMessage.GetThrowMessage("no support Skip take, use PageForEach", "不支持Skip Take,请使用 Queryale.PageForEach")); diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs new file mode 100644 index 000000000..a8c4980ae --- /dev/null +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + internal class ExpressionItems + { + /// + /// 1 memeber, 2 class ,3 method + /// + public int Type { get; set; } + public EntityInfo ParentEntityInfo { get; set; } + public EntityInfo ThisEntityInfo { get; set; } + public Expression Expression { get; set; } + public Navigate Nav + { + get + { + if (Expression is MemberExpression) + { + var name = (Expression as MemberExpression).Member.Name; + var navColumn = ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == name); + return navColumn == null ? null : navColumn.Navigat; + } + return null; + } + } + + } +} diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MapperExpressionResolve.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MapperExpressionResolve.cs index bb134ad88..c8d0d131b 100644 --- a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MapperExpressionResolve.cs +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MapperExpressionResolve.cs @@ -318,11 +318,11 @@ namespace SqlSugar void Error01() { - Check.Exception(mappers == null, ErrorMessage.GetThrowMessage(expression.ToString() + "no support", "当前表达式" + expression.ToString() + "必须在Mapper之后使用")); + Check.Exception(mappers == null, ErrorMessage.GetThrowMessage(expression.ToString() + "no support", "当前表达式" + expression.ToString() + " 不支持,查看导航是否配置正确等 ")); } void ThrowTrue(bool isError) { - Check.Exception(isError, ErrorMessage.GetThrowMessage(expression.ToString() + "no support", "不支持表达式" + expression.ToString() + " 1.检查当前表达式中的别名是否与Mapper中的一致 2.目前只支持 1对1 Mapper下的 Where ")); + Check.Exception(isError, ErrorMessage.GetThrowMessage(expression.ToString() + "no support", "不支持表达式" + expression.ToString() + " ,查看导航是否配置正确等 ")); } } diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs index 19748e87a..3ba2bd0bf 100644 --- a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs @@ -59,6 +59,7 @@ namespace SqlSugar else if (isMemberValue) { var nav = new OneToOneNavgateExpression(this.Context?.SugarContext?.Context); + var navN = new OneToOneNavgateExpressionN(this.Context?.SugarContext?.Context); if (nav.IsNavgate(expression)) { var value = nav.GetSql(); @@ -72,6 +73,19 @@ namespace SqlSugar AppendValue(parameter, isLeft, value); } } + else if (navN.IsNavgate(expression)) + { + var value = navN.GetMemberSql(); + this.Context.SingleTableNameSubqueryShortName = navN.shorName; + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + } else { ResolveMemberValue(parameter, baseParameter, isLeft, isSetTempData, expression); diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs index 9d824fe46..820457e8e 100644 --- a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs @@ -253,6 +253,15 @@ namespace SqlSugar return; } + OneToManyNavgateExpressionN nav2 = new OneToManyNavgateExpressionN(this.Context?.SugarContext?.Context, this); + if (nav2.IsNavgate(express)) + { + var sql = nav2.GetSql(); + this.Context.SingleTableNameSubqueryShortName = nav2.shorName; + base.AppendValue(parameter, isLeft, sql); + return; + } + var constValue = ExpressionTool.DynamicInvoke(express); if (constValue is MapperSql) { diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs new file mode 100644 index 000000000..6fbecb217 --- /dev/null +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + internal class OneToManyNavgateExpressionN + { + #region Constructor + public SqlSugarProvider context; + public string shorName; + public EntityInfo entityInfo; + public List items; + public string whereSql; + public MethodCallExpressionResolve methodCallExpressionResolve; + public OneToManyNavgateExpressionN(SqlSugarProvider context, MethodCallExpressionResolve methodCallExpressionResolve) + { + this.context = context; + this.methodCallExpressionResolve= methodCallExpressionResolve; + } + #endregion + + internal bool IsNavgate(Expression expression) + { + var result = false; + var exp = expression; + if (exp is UnaryExpression) + { + exp = (exp as UnaryExpression).Operand; + } + if (exp is MethodCallExpression) + { + var memberExp=exp as MethodCallExpression; + if (memberExp.Method.Name.IsIn("Any","Count") && memberExp.Arguments.Count>0 && memberExp.Arguments[0] is MemberExpression ) + { + result = ValiteOneManyCall(result, memberExp, memberExp.Arguments[0] as MemberExpression, memberExp.Arguments[0]); + if (memberExp.Arguments.Count > 1) + { + whereSql = GetWhereSql(memberExp); + } + } + } + return result; + } + private bool ValiteOneManyCall(bool result,MethodCallExpression callExpression, MemberExpression memberExp, Expression childExpression) + { + if (childExpression != null && childExpression is MemberExpression) + { + var oldChildExpression = childExpression; + var child2Expression = (childExpression as MemberExpression).Expression; + if (child2Expression == null || (child2Expression is ConstantExpression)) + { + return false; + } + items = new List(); + var childType = oldChildExpression.Type; + if (!childType.FullName.IsCollectionsList()) + { + return false; + } + childType = childType.GetGenericArguments()[0]; + items.Add(new ExpressionItems() { Type = 3, Expression = callExpression, ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(childType) }); + items.Add(new ExpressionItems() { Type = 2, Expression = oldChildExpression, ThisEntityInfo = this.context.EntityMaintenance.GetEntityInfo(childType), ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type) }); + if (items.Any(it => it.Type == 2 && it.Nav == null)) + { + return false; + } + while (child2Expression != null) + { + if (IsClass(child2Expression)) + { + items.Add(new ExpressionItems() { Type = 2, Expression = child2Expression, ThisEntityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type), ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(GetMemberExpression(child2Expression).Type) }); + child2Expression = GetMemberExpression(child2Expression); + + } + else if (IsParameter(child2Expression)) + { + shorName = child2Expression.ToString(); + entityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type); + break; + } + else + { + break; + } + } + if (!items.Any(it => it.Type == 2 && it.Nav == null)) + { + return true; + } + } + return result; + } + public object GetSql() + { + MapperSql MapperSql = new MapperSql(); + var memberInfo = this.items.Where(it => it.Type == 3).First(); + var subInfos = this.items.Where(it => it.Type == 2).Reverse().ToList(); + var formInfo = subInfos.First(); + var joinInfos = subInfos.Skip(1).ToList(); + var i = 0; + var masterShortName = formInfo.ThisEntityInfo.DbTableName + i; + var queryable = this.context.Queryable(masterShortName).AS(formInfo.ThisEntityInfo.DbTableName); + i++; + var lastShortName = ""; + var index = 0; + foreach (var item in joinInfos) + { + var shortName = item.ThisEntityInfo.DbTableName + i; + EntityColumnInfo pkColumn; + EntityColumnInfo navColum; + if (index == 0) + { + pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name); + navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); + } + else + { + pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); + navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name); + } + Check.ExceptionEasy(pkColumn == null, $"{item.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{item.ThisEntityInfo.EntityName} 缺少主键"); + var on = $" {shortName}.{queryable.SqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName)}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{queryable.SqlBuilder.GetTranslationColumnName(navColum.DbColumnName)}"; + queryable.AddJoinInfo(item.ThisEntityInfo.DbTableName, shortName, on, JoinType.Inner); + ++i; + index++; + lastShortName = shortName; + formInfo = item; + } + queryable.Select($" COUNT(1)"); + var last = subInfos.First(); + var FirstPkColumn = last.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); + Check.ExceptionEasy(FirstPkColumn == null, $"{ last.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{ last.ThisEntityInfo.EntityName} 缺少主键"); + var PkColumn = last.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == last.Nav.Name); + Check.ExceptionEasy(PkColumn == null, $"{ last.ParentEntityInfo.EntityName} no found {last.Nav.Name}", $"{ last.ParentEntityInfo.EntityName} 不存在 {last.Nav.Name}"); + queryable.Where($" {this.shorName}.{ queryable.SqlBuilder.GetTranslationColumnName(PkColumn.DbColumnName)} = {masterShortName}.{queryable.SqlBuilder.GetTranslationColumnName(FirstPkColumn.DbColumnName)} "); + queryable.WhereIF(this.whereSql.HasValue(), GetWhereSql1(this.whereSql,lastShortName, joinInfos, queryable.SqlBuilder)); + MapperSql.Sql = $"( {queryable.ToSql().Key} ) "; + if ((memberInfo.Expression as MethodCallExpression).Method.Name == "Any") + { + MapperSql.Sql = $"( {MapperSql.Sql}>0 ) "; + + } + return MapperSql; + } + + + #region Helper + private string GetWhereSql1(string wheresql,string lastShortName, List joinInfos,ISqlBuilder sqlBuilder) + { + var sql = wheresql; + if (sql == null) return sql; + joinInfos.Last().ThisEntityInfo.Columns.ForEach(it => + { + this.whereSql = this.whereSql.Replace(sqlBuilder.GetTranslationColumnName(it.DbColumnName), + lastShortName+"." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)); + + }); + return sql; + } + + private string GetWhereSql(MethodCallExpression memberExp) + { + var whereExp = memberExp.Arguments[1]; + var result = this.methodCallExpressionResolve.GetNewExpressionValue(whereExp); + return result; + } + private static bool IsParameter(Expression child2Expression) + { + return child2Expression.Type.IsClass() && child2Expression is ParameterExpression; + } + + private static Expression GetMemberExpression(Expression child2Expression) + { + return (child2Expression as MemberExpression).Expression; + } + + private static bool IsClass(Expression child2Expression) + { + return child2Expression.Type.IsClass() && child2Expression is MemberExpression; + } + #endregion + } +} diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToOneNavgateExpressionN.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToOneNavgateExpressionN.cs new file mode 100644 index 000000000..a0b625554 --- /dev/null +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/OneToOneNavgateExpressionN.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + internal class OneToOneNavgateExpressionN + { + #region Constructor + public string shorName { get; set; } + public EntityInfo entityInfo; + public List items; + public SqlSugarProvider context; + public OneToOneNavgateExpressionN(SqlSugarProvider context) + { + this.context = context; + } + #endregion + + #region Api&Core + + public bool IsNavgate(Expression expression) + { + if (this.context == null) return false; + var result = false; + var exp = expression; + if (exp is UnaryExpression) + { + exp = (exp as UnaryExpression).Operand; + } + if (exp is MemberExpression) + { + var memberExp = exp as MemberExpression; + var childExpression = memberExp.Expression; + result = ValidateIsJoinMember(result, memberExp, childExpression); + } + return result; + } + public MapperSql GetMemberSql() + { + MapperSql MapperSql = new MapperSql(); + var memberInfo = this.items.Where(it => it.Type == 1).First(); + var subInfos = this.items.Where(it => it.Type == 2).Reverse().ToList(); + var formInfo = subInfos.First(); + var joinInfos = subInfos.Skip(1).ToList(); + var i = 0; + var masterShortName = formInfo.ThisEntityInfo.DbTableName + i; + var queryable = this.context.Queryable(masterShortName).AS(formInfo.ThisEntityInfo.DbTableName); + i++; + var lastShortName = ""; + foreach (var item in joinInfos) + { + var shortName = item.ThisEntityInfo.DbTableName + i; + var pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); + var navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name); + Check.ExceptionEasy(pkColumn == null, $"{item.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{item.ThisEntityInfo.EntityName} 缺少主键"); + var on = $" {shortName}.{queryable.SqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName)}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{queryable.SqlBuilder.GetTranslationColumnName(navColum.DbColumnName)}"; + queryable.AddJoinInfo(item.ThisEntityInfo.DbTableName, shortName, on, JoinType.Inner); + ++i; + lastShortName = shortName; + formInfo = item; + } + var selectProperyInfo = ExpressionTool.GetMemberName(memberInfo.Expression); + var selectColumnInfo = memberInfo.ParentEntityInfo.Columns.First(it => it.PropertyName == selectProperyInfo); + queryable.Select($" {lastShortName}.{queryable.SqlBuilder.GetTranslationColumnName(selectColumnInfo.DbColumnName)}"); + var last = subInfos.First(); + var FirstPkColumn = last.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); + Check.ExceptionEasy(FirstPkColumn == null, $"{ last.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{ last.ThisEntityInfo.EntityName} 缺少主键"); + var PkColumn = last.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == last.Nav.Name); + Check.ExceptionEasy(PkColumn == null, $"{ last.ParentEntityInfo.EntityName} no found {last.Nav.Name}", $"{ last.ParentEntityInfo.EntityName} 不存在 {last.Nav.Name}"); + queryable.Where($" {this.shorName}.{queryable.SqlBuilder.GetTranslationColumnName(PkColumn.DbColumnName)} = {masterShortName}.{queryable.SqlBuilder.GetTranslationColumnName(FirstPkColumn.DbColumnName)} "); + MapperSql.Sql = "( " + queryable.ToSql().Key + " ) "; + return MapperSql; + } + private bool ValidateIsJoinMember(bool result, MemberExpression memberExp, Expression childExpression) + { + if (childExpression != null && childExpression is MemberExpression) + { + var oldChildExpression = childExpression; + var child2Expression = (childExpression as MemberExpression).Expression; + if (child2Expression == null||(child2Expression is ConstantExpression)) + { + return false; + } + items = new List(); + items.Add(new ExpressionItems() { Type=1 , Expression= memberExp, ParentEntityInfo= this.context.EntityMaintenance.GetEntityInfo(oldChildExpression.Type )}); + items.Add(new ExpressionItems() { Type = 2, Expression = oldChildExpression, ThisEntityInfo=this.context.EntityMaintenance.GetEntityInfo(oldChildExpression.Type), ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type) }); + if (items.Any(it => it.Type == 2 && it.Nav == null)) + { + return false; + } + while (child2Expression != null) + { + if (IsClass(child2Expression)) + { + items.Add(new ExpressionItems() { Type = 2, Expression = child2Expression, ThisEntityInfo=this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type), ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(GetMemberExpression(child2Expression).Type) }); + child2Expression = GetMemberExpression(child2Expression); + + } + else if (IsParameter(child2Expression)) + { + shorName = child2Expression.ToString(); + entityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type); + break; + } + else + { + break; + } + } + if (!items.Any(it => it.Type == 2 && it.Nav == null)) + { + return true; + } + } + return result; + } + #endregion + + #region Helper + + private static bool IsParameter(Expression child2Expression) + { + return child2Expression.Type.IsClass() && child2Expression is ParameterExpression; + } + + private static Expression GetMemberExpression(Expression child2Expression) + { + return (child2Expression as MemberExpression).Expression; + } + + private static bool IsClass(Expression child2Expression) + { + return child2Expression.Type.IsClass() && child2Expression is MemberExpression; + } + #endregion + + } +} diff --git a/Src/Asp.NetCore2/SqlSugar/Interface/IQueryable.cs b/Src/Asp.NetCore2/SqlSugar/Interface/IQueryable.cs index 794d5f9f1..bc8e07523 100644 --- a/Src/Asp.NetCore2/SqlSugar/Interface/IQueryable.cs +++ b/Src/Asp.NetCore2/SqlSugar/Interface/IQueryable.cs @@ -136,7 +136,9 @@ namespace SqlSugar List ToList(Expression> expression); List ToList(); List SetContext(Expression> thisFiled, Expression> mappingFiled, ParameterT parameter); + List SetContext(Expression> thisFiled1, Expression> mappingFiled1, Expression> thisFiled2, Expression> mappingFiled2, ParameterT parameter); Task > SetContextAsync(Expression> thisFiled, Expression> mappingFiled, ParameterT parameter); + Task> SetContextAsync(Expression> thisFiled1, Expression> mappingFiled1, Expression> thisFiled2, Expression> mappingFiled2, ParameterT parameter); Dictionary ToDictionary(Expression> key, Expression> value); Task> ToDictionaryAsync(Expression> key, Expression> value); List> ToDictionaryList();