diff --git a/OrmTest/UnitTest/Query/SelectQuery.cs b/OrmTest/UnitTest/Query/SelectQuery.cs index 833cc18d6..e8b87b723 100644 --- a/OrmTest/UnitTest/Query/SelectQuery.cs +++ b/OrmTest/UnitTest/Query/SelectQuery.cs @@ -38,20 +38,24 @@ namespace OrmTest.UnitTest #region dr ot entity db.IgnoreComumns.Add("TestId", "Student"); - var s1 = db.Queryable().Select(it => new ViewModelStudent2 { Name=it.Name,Student=it}).ToList(); - var s2 = db.Queryable().Select(it => new { id=it.Id,w=new { x=it } }).ToList(); + var s1 = db.Queryable().Select(it => new ViewModelStudent2 { Name = it.Name, Student = it }).ToList(); + var s2 = db.Queryable().Select(it => new { id = it.Id, w = new { x = it } }).ToList(); var s3 = db.Queryable().Select(it => new { newid = it.Id }).ToList(); var s4 = db.Queryable().Select(it => new { newid = it.Id, obj = it }).ToList(); - var s5 = db.Queryable().Select(it => new ViewModelStudent2 { Student = it, Name =it.Name }).ToList(); + var s5 = db.Queryable().Select(it => new ViewModelStudent2 { Student = it, Name = it.Name }).ToList(); #endregion #region sql and parameters validate - var ss0 = db.Queryable((st,sc)=>new object[] { + var ss0 = db.Queryable((st, sc) => new object[] { JoinType.Inner,st.Id==sc.Id - }).GroupBy(st => st.Id).Select(st => new { avgId=NBORM.AggregateAvg(st.Id) }).ToSql(); - base.Check(" SELECT AVG([st].[Id]) AS [avgId] FROM [Student] st Inner JOIN School sc ON ( [st].[Id] = [sc].[Id] ) GROUP BY [st].[Id] ", null, - ss0.Key, null," ss0 Error"); + }).GroupBy(st => st.Id).Having(sc => NBORM.AggregateAvg(sc.Id) == 1).Select(st => new { avgId = NBORM.AggregateAvg(st.Id) }).ToSql(); + base.Check("SELECT AVG([st].[Id]) AS [avgId] FROM [Student] st Inner JOIN School sc ON ( [st].[Id] = [sc].[Id] ) GROUP BY [st].[Id] HAVING (AVG([sc].[Id]) = @Const0 ) ", + new List() { + new SugarParameter("@Const0",1) + } + , + ss0.Key, ss0.Value, " ss0 Error"); var ss1 = db.Queryable((st, st2) => new object[] { diff --git a/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs b/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs index 57c35c990..6fb327a34 100644 --- a/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs +++ b/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs @@ -99,6 +99,45 @@ namespace SqlSugar this._Where(expression); return this; } + + public ISugarQueryable Having(Expression> expression) { + this._Having(expression); + return this; + } + public ISugarQueryable Having(string whereString, object whereObj = null) + { + + QueryBuilder.HavingInfos = SqlBuilder.AppendHaving(whereString); + if (whereObj != null) + QueryBuilder.QueryPars.AddRange(Context.Database.GetParameters(whereObj)); + return this; + } + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public virtual ISugarQueryable WhereIF(bool isWhere, Expression> expression) { if (!isWhere) return this; @@ -539,7 +578,13 @@ namespace SqlSugar GroupBy(lamResult.GetResultString()); return this; } - + protected ISugarQueryable _Having(Expression expression) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple); + Having(lamResult.GetResultString()); + return this; + } private List _ToList() { var sqlObj = this.ToSql(); diff --git a/SqlSugar/Abstract/SqlBuilderProvider/DMLBuilder/QueryBuilder.cs b/SqlSugar/Abstract/SqlBuilderProvider/DMLBuilder/QueryBuilder.cs index 6d31cdc61..6a01db90b 100644 --- a/SqlSugar/Abstract/SqlBuilderProvider/DMLBuilder/QueryBuilder.cs +++ b/SqlSugar/Abstract/SqlBuilderProvider/DMLBuilder/QueryBuilder.cs @@ -19,6 +19,7 @@ namespace SqlSugar #region Private Fileds private List _JoinQueryInfos; private List _WhereInfos; + private string _HavingInfos; private string _TableNameString; #endregion @@ -61,6 +62,17 @@ namespace SqlSugar } set { _WhereInfos = value; } } + public virtual string HavingInfos + { + get + { + return _HavingInfos; + } + set + { + _HavingInfos = value; + } + } #endregion #region Lambada Type @@ -155,8 +167,10 @@ namespace SqlSugar return "AVG({0})"; } } - public virtual string InTemplate { - get { + public virtual string InTemplate + { + get + { return "{0} IN ({1}) "; } } @@ -185,7 +199,7 @@ namespace SqlSugar public virtual string ToSqlString() { sql = new StringBuilder(); - sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString,(Skip!=null||Take!=null)?null:GetOrderByString); + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString+HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); if (IsCount) { return sql.ToString(); } if (Skip != null && Take == null) { diff --git a/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs b/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs index eb0048004..ffdb39749 100644 --- a/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs +++ b/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs @@ -22,6 +22,10 @@ namespace SqlSugar { return isWhere ? (" WHERE " + sqlString ):( " AND " + sqlString); } + public string AppendHaving(string sqlString) + { + return " HAVING " + sqlString; + } public DeleteBuilder DeleteBuilder { diff --git a/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs b/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs index 9b2c4bfff..69cb3bff7 100644 --- a/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs +++ b/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs @@ -54,6 +54,12 @@ namespace SqlSugar parameter.Context.Result.Append(base.Context.GetAsString(memberName, parameterName)); this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); } + else if (item is MethodCallExpression) + { + base.Expression = item; + base.Start(); + parameter.Context.Result.Append(base.Context.GetAsString(memberName, parameter.CommonTempData.ObjToString())); + } else if (item is MemberExpression) { if (base.Context.Result.IsLockCurrentParameter == false) diff --git a/SqlSugar/Interface/IQueryable.cs b/SqlSugar/Interface/IQueryable.cs index 80d109eb4..16871e5fa 100644 --- a/SqlSugar/Interface/IQueryable.cs +++ b/SqlSugar/Interface/IQueryable.cs @@ -24,6 +24,15 @@ namespace SqlSugar ISugarQueryable Where(Expression> expression); ISugarQueryable Where(Expression> expression) ; ISugarQueryable Where(Expression> expression) ; + + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(string whereString, object whereObj = null); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); ISugarQueryable WhereIF(bool isWhere,string whereString, object whereObj = null); ISugarQueryable WhereIF(bool isWhere, Expression> expression); diff --git a/SqlSugar/Interface/ISqlBuilder/ISqlBuilder.cs b/SqlSugar/Interface/ISqlBuilder/ISqlBuilder.cs index 82099fabc..66154481a 100644 --- a/SqlSugar/Interface/ISqlBuilder/ISqlBuilder.cs +++ b/SqlSugar/Interface/ISqlBuilder/ISqlBuilder.cs @@ -11,6 +11,7 @@ namespace SqlSugar SqlSugarClient Context { get; set; } CommandType CommandType { get; set; } String AppendWhereOrAnd(bool isWhere, string sqlString); + string AppendHaving(string sqlString); SqlQueryBuilder SqlQueryBuilder { get; set; } QueryBuilder QueryBuilder { get; set; } InsertBuilder InsertBuilder { get; set; }