From 68cf1416c7cc681d173efd1cd9833166e2b0f09f Mon Sep 17 00:00:00 2001 From: sunkaixuan <610262374@qq.com> Date: Mon, 2 May 2022 21:04:36 +0800 Subject: [PATCH] Update exp to sql --- .../SqlServerTest/UnitTest/UCustom012.cs | 10 +- .../Common/ExpressionItems.cs | 2 +- .../MethodCallExpressionResolve.cs | 9 ++ .../OneToManyNavgateExpressionN.cs | 118 ++++++++++++++---- 4 files changed, 111 insertions(+), 28 deletions(-) diff --git a/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs b/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs index 26548e8a2..2b2b40759 100644 --- a/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs +++ b/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs @@ -32,13 +32,14 @@ namespace OrmTest db.Insertable(new SchoolA() { SchoolId = 1, CityId= 1001001, School_Name = "北大" }).ExecuteCommand(); db.Insertable(new SchoolA() { SchoolId = 2 , CityId=2,School_Name = "清华" }).ExecuteCommand(); + db.Insertable(new SchoolA() { SchoolId = 3, CityId = 3, School_Name = "青鸟" }).ExecuteCommand(); db.Insertable(new StudentA() { StudentId = 1, SchoolId = 1, Name = "北大jack" }).ExecuteCommand(); db.Insertable(new StudentA() { StudentId = 2, SchoolId = 1, Name = "北大tom" }).ExecuteCommand(); db.Insertable(new StudentA() { StudentId = 3, SchoolId = 2, Name = "清华jack" }).ExecuteCommand(); db.Insertable(new StudentA() { StudentId = 4, SchoolId = 2, Name = "清华tom" }).ExecuteCommand(); db.Insertable(new StudentA() { StudentId = 5, SchoolId = null, Name = "清华tom" }).ExecuteCommand(); - + db.Insertable(new StudentA() { StudentId = 6, SchoolId = 3, Name = "青鸟学生" }).ExecuteCommand(); db.Insertable(new TeacherA() { SchoolId = 1, Id = 1, Name = "北大老师01" }).ExecuteCommand(); db.Insertable(new TeacherA() { SchoolId = 1, Id = 2, Name = "北大老师02" }).ExecuteCommand(); @@ -76,6 +77,13 @@ namespace OrmTest Check.Exception(string.Join(",", list22.Select(it => it.StudentId)) != string.Join(",", list33.Select(it => it.StudentId)), "unit error"); + + var list333 = db.Queryable() + .Includes(it => it.SchoolA,it=>it.TeacherList) + .Where(it => it.SchoolA.TeacherList.Any()) + .ToList(); + + var list3 = db.Queryable() .Includes(x => x.SchoolA, x => x.RoomList)//2个参数就是 then Include .Includes(x => x.SchoolA, x => x.TeacherList)//2个参数就是 then Include diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs index 0ded2f454..a8c4980ae 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionItems.cs @@ -10,7 +10,7 @@ namespace SqlSugar internal class ExpressionItems { /// - /// 0 memeber, 2 method ,3 class + /// 1 memeber, 2 class ,3 method /// public int Type { get; set; } public EntityInfo ParentEntityInfo { get; set; } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs index 9d824fe46..820457e8e 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs +++ b/Src/Asp.Net/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.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs index 93cea3de9..921ab25b0 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs @@ -9,12 +9,19 @@ namespace SqlSugar { internal class OneToManyNavgateExpressionN { - private SqlSugarProvider context; + #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) { @@ -29,32 +36,16 @@ namespace SqlSugar var memberExp=exp as MethodCallExpression; if (memberExp.Method.Name.IsIn("Any","Count") && memberExp.Arguments.Count>0 && memberExp.Arguments[0] is MemberExpression ) { - result = ValidateNav(result, memberExp.Arguments[0] as MemberExpression, memberExp.Arguments[0]); + result = ValiteOneManyCall(result, memberExp, memberExp.Arguments[0] as MemberExpression, memberExp.Arguments[0]); if (memberExp.Arguments.Count > 1) { + whereSql = GetWhereSql(memberExp); } } } return result; } - - private string GetWhereSql(MethodCallExpression memberExp) - { - - return null; - } - - private bool ValidateNav(bool result, MemberExpression memberExp, Expression childExpression) - { - if (childExpression != null && childExpression is MemberExpression) - { - result = ValidateIsJoinMember(result,memberExp, childExpression); - } - - return result; - } - List items; - private bool ValidateIsJoinMember(bool result, MemberExpression memberExp, Expression childExpression) + private bool ValiteOneManyCall(bool result,MethodCallExpression callExpression, MemberExpression memberExp, Expression childExpression) { if (childExpression != null && childExpression is MemberExpression) { @@ -65,8 +56,14 @@ namespace SqlSugar 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) }); + 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; @@ -97,10 +94,79 @@ namespace SqlSugar } 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}.{pkColumn.DbColumnName}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{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}.{PkColumn.DbColumnName} = {masterShortName}.{FirstPkColumn.DbColumnName} "); + MapperSql.Sql = $"( {queryable.ToSql().Key} ) "; + if ((memberInfo.Expression as MethodCallExpression).Method.Name == "Any") + { + MapperSql.Sql = $"( {MapperSql.Sql}>0 ) "; + + } + return MapperSql; + } + + #region Helper + 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; + } - internal object GetSql() + private static bool IsClass(Expression child2Expression) { - throw new NotImplementedException(); + return child2Expression.Type.IsClass() && child2Expression is MemberExpression; } + #endregion } }