diff --git a/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs b/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs index 10d5e4639..42fa27102 100644 --- a/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs +++ b/Src/Asp.Net/SqlServerTest/UnitTest/UCustom012.cs @@ -55,6 +55,7 @@ namespace OrmTest var list2 = db.Queryable() .Includes(x => x.SchoolA, x => x.RoomList)//2个参数就是 then Include .Includes(x => x.Books) + .Where(x=>x.Books.Any()) .Where(x => x.SchoolA.SchoolName == "北大") .ToList(); @@ -98,13 +99,16 @@ namespace OrmTest var list21111 = new List(); - db.Queryable() + var xxx= db.Queryable() .Includes(it => it.Child) .Includes(it => it.Parent) - .ForEach(item => { - list21111.Add(item); - }, 2); + .Where(it=>it.Child.Any()) + .ToList(); + db.ThenMapper(xxx, it => + { + it.Child = it.Child.OrderBy(x => x.Id).ToList(); + }); //var json = db.Utilities.SerializeObject(list4); db.CodeFirst.InitTables(); diff --git a/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs b/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs index 7d920930b..01042f7d5 100644 --- a/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs +++ b/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs @@ -221,6 +221,7 @@ namespace SqlSugar this.MappingType = MappingTableType; this.MappingAId = typeAiD; this.MappingBId = typeBId; + this.NavigatType = NavigatType.ManyToMany; } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs index 1b83da685..b8a760a03 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs @@ -244,6 +244,15 @@ namespace SqlSugar { try { + OneToManyNavgateExpression nav=new OneToManyNavgateExpression(this.Context?.SugarContext?.Context); + if (nav.IsNavgate(express)) + { + var sql = nav.GetSql(); + this.Context.SingleTableNameSubqueryShortName = nav.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/NavgateExpression.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NavgateExpression.cs index 6f5e4d357..c13880624 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NavgateExpression.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NavgateExpression.cs @@ -22,36 +22,43 @@ namespace SqlSugar internal bool IsNavgate(Expression expression) { + var result = false; var exp = expression; if (exp is UnaryExpression) { exp = (exp as UnaryExpression).Operand; } - if (exp is MemberExpression) + if (exp is MemberExpression) { - var memberExp=exp as MemberExpression; + var memberExp = exp as MemberExpression; var childExpression = memberExp.Expression; - if (childExpression != null && childExpression is MemberExpression) + result = ValidateNav(result, memberExp, childExpression); + } + return result; + } + + private bool ValidateNav(bool result, MemberExpression memberExp, Expression childExpression) + { + if (childExpression != null && childExpression is MemberExpression) + { + var child2Expression = (childExpression as MemberExpression).Expression; + if (child2Expression.Type.IsClass() && child2Expression is ParameterExpression) { - var child2Expression = (childExpression as MemberExpression).Expression; - if (child2Expression.Type.IsClass()&& child2Expression is ParameterExpression) + var entity = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type); + if (entity.Columns.Any(x => x.PropertyName == (childExpression as MemberExpression).Member.Name && x.Navigat != null)) { - var entity= this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type); - if (entity.Columns.Any(x => x.PropertyName == (childExpression as MemberExpression).Member.Name && x.Navigat != null)) - { - EntityInfo = entity; - ShorName = child2Expression.ToString(); - MemberName= memberExp.Member.Name; - ProPertyEntity = this.context.EntityMaintenance.GetEntityInfo(childExpression.Type); - Navigat = entity.Columns.FirstOrDefault(x => x.PropertyName == (childExpression as MemberExpression).Member.Name).Navigat; - return true; - } + EntityInfo = entity; + ShorName = child2Expression.ToString(); + MemberName = memberExp.Member.Name; + ProPertyEntity = this.context.EntityMaintenance.GetEntityInfo(childExpression.Type); + Navigat = entity.Columns.FirstOrDefault(x => x.PropertyName == (childExpression as MemberExpression).Member.Name).Navigat; + result = true; } } } - return false; - } + return result; + } internal MapperSql GetSql() { diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NavgateExpressionCall.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NavgateExpressionCall.cs new file mode 100644 index 000000000..94801c262 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NavgateExpressionCall.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + internal class OneToManyNavgateExpression + { + private SqlSugarProvider context; + private EntityInfo EntityInfo; + private EntityInfo ProPertyEntity; + private Navigat Navigat; + public string ShorName; + private string MemberName; + private string MethodName; + public OneToManyNavgateExpression(SqlSugarProvider context) + { + this.context = context; + } + + 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; + MethodName = memberExp.Method.Name; + 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]); + } + } + return result; + } + + private bool ValidateNav(bool result, MemberExpression memberExp, Expression childExpression) + { + if (childExpression != null && childExpression is MemberExpression) + { + var child2Expression = (childExpression as MemberExpression).Expression; + if (child2Expression.Type.IsClass() && child2Expression is ParameterExpression) + { + var rootType = child2Expression.Type; + var rootEntity = this.context.EntityMaintenance.GetEntityInfo(rootType); + var type= childExpression.Type.GetGenericArguments()[0]; + var entity = this.context.EntityMaintenance.GetEntityInfo(type); + if (rootEntity.Columns.Any(x => x.PropertyName == (childExpression as MemberExpression).Member.Name && x.Navigat != null)) + { + EntityInfo = rootEntity; + ShorName = child2Expression.ToString(); + MemberName = memberExp.Member.Name; + ProPertyEntity = entity; + Navigat = rootEntity.Columns.FirstOrDefault(x => x.PropertyName == (childExpression as MemberExpression).Member.Name).Navigat; + result = true; + } + } + } + + return result; + } + internal MapperSql GetSql() + { + if (Navigat.NavigatType == NavigatType.OneToMany) + { + return GetOneToManySql(); + } + else + { + return GetManyToManySql(); + } + + } + private MapperSql GetManyToManySql() + { + var pk = this.ProPertyEntity.Columns.First(it => it.IsPrimarykey == true).DbColumnName; + var name = this.EntityInfo.Columns.First(it => it.PropertyName == Navigat.Name).DbColumnName; + var selectName = this.ProPertyEntity.Columns.First(it => it.PropertyName == MemberName).DbColumnName; + MapperSql mapper = new MapperSql(); + var queryable = this.context.Queryable(); + pk = queryable.QueryBuilder.Builder.GetTranslationColumnName(pk); + name = queryable.QueryBuilder.Builder.GetTranslationColumnName(name); + selectName = queryable.QueryBuilder.Builder.GetTranslationColumnName(selectName); + mapper.Sql = queryable + .AS(this.ProPertyEntity.DbTableName) + .Where($" {ShorName}.{name}={pk} ").Select(selectName).ToSql().Key; + mapper.Sql = $" ({mapper.Sql}) "; + mapper.Sql = GetMethodSql(mapper.Sql); + return mapper; + } + private MapperSql GetOneToManySql() + { + var pk = this.EntityInfo.Columns.First(it => it.IsPrimarykey == true).DbColumnName; + var name = this.ProPertyEntity.Columns.First(it => it.PropertyName == Navigat.Name).DbColumnName; + //var selectName = this.ProPertyEntity.Columns.First(it => it.PropertyName == MemberName).DbColumnName; + MapperSql mapper = new MapperSql(); + var queryable = this.context.Queryable(); + pk = queryable.QueryBuilder.Builder.GetTranslationColumnName(pk); + name = queryable.QueryBuilder.Builder.GetTranslationColumnName(name); + //selectName = queryable.QueryBuilder.Builder.GetTranslationColumnName(selectName); + mapper.Sql = queryable + .AS(this.ProPertyEntity.DbTableName) + .Where($" {name}={ShorName}.{pk} ").Select(" COUNT(1) ").ToSql().Key; + mapper.Sql = $" ({mapper.Sql}) "; + mapper.Sql = GetMethodSql(mapper.Sql); + return mapper; + } + + private string GetMethodSql(string sql) + { + if (MethodName == "Any") + { + return $" ({sql}>0 ) "; + } + return sql; + } + + } +} diff --git a/Src/Asp.Net/SqlSugar/SqlSugar.csproj b/Src/Asp.Net/SqlSugar/SqlSugar.csproj index ac16ace5f..dac86fb7e 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugar.csproj +++ b/Src/Asp.Net/SqlSugar/SqlSugar.csproj @@ -105,6 +105,7 @@ +