- 优化 ISelect.GroupBy 查询,增加 .Value 实现聚合源字段查询,ToList(a => a.Sum(a.Value.Score));

- 增加 Expression string.Concat;
This commit is contained in:
28810
2019-04-25 12:34:09 +08:00
parent ddd5e81a67
commit 02ab4949c0
44 changed files with 466 additions and 86 deletions

View File

@ -679,14 +679,14 @@ namespace FreeSql.Internal.CommonProvider {
protected TMember InternalSum<TMember>(Expression exp) => this.ToList<TMember>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault();
async protected Task<TMember> InternalSumAsync<TMember>(Expression exp) => (await this.ToListAsync<TMember>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})")).FirstOrDefault();
protected ISelectGrouping<TKey> InternalGroupBy<TKey>(Expression columns) {
protected ISelectGrouping<TKey, TValue> InternalGroupBy<TKey, TValue>(Expression columns) {
var map = new ReadAnonymousTypeInfo();
var field = new StringBuilder();
var index = -10000; //临时规则,不返回 as1
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null);
this.GroupBy(field.Length > 0 ? field.Remove(0, 2).ToString() : null);
return new SelectGroupingProvider<TKey>(this, map, _commonExpression);
return new SelectGroupingProvider<TKey, TValue>(this, map, _commonExpression, _tables);
}
protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) {
_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null);

View File

@ -44,10 +44,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> (exp?.Body);
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) {

View File

@ -87,10 +87,10 @@ namespace FreeSql.Internal.CommonProvider {
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;// { this.InternalFrom(exp?.Body); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public ISelectGrouping<TKey> GroupBy<TKey>(Expression<Func<T1, TKey>> columns) {
if (columns == null) return this.InternalGroupBy<TKey>(columns);
public ISelectGrouping<TKey, T1> GroupBy<TKey>(Expression<Func<T1, TKey>> columns) {
if (columns == null) return this.InternalGroupBy<TKey, T1>(columns);
_tables[0].Parameter = columns.Parameters[0];
return this.InternalGroupBy<TKey>(columns);
return this.InternalGroupBy<TKey, T1>(columns);
}
public TMember Max<TMember>(Expression<Func<T1, TMember>> column) {

View File

@ -28,10 +28,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2>.GroupBy<TKey>(Expression<Func<T1, T2, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2)> ISelect<T1, T2>.GroupBy<TKey>(Expression<Func<T1, T2, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2)>(exp?.Body);
}
TMember ISelect<T1, T2>.Max<TMember>(Expression<Func<T1, T2, TMember>> column) {

View File

@ -30,10 +30,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3>.GroupBy<TKey>(Expression<Func<T1, T2, T3, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3)> ISelect<T1, T2, T3>.GroupBy<TKey>(Expression<Func<T1, T2, T3, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3)>(exp?.Body);
}
TMember ISelect<T1, T2, T3>.Max<TMember>(Expression<Func<T1, T2, T3, TMember>> column) {

View File

@ -32,10 +32,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4)> ISelect<T1, T2, T3, T4>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4)>(exp?.Body);
}
TMember ISelect<T1, T2, T3, T4>.Max<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) {

View File

@ -34,10 +34,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4, T5)> ISelect<T1, T2, T3, T4, T5>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5)>(exp?.Body);
}
TMember ISelect<T1, T2, T3, T4, T5>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) {

View File

@ -36,10 +36,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4, T5, T6)> ISelect<T1, T2, T3, T4, T5, T6>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6)>(exp?.Body);
}
TMember ISelect<T1, T2, T3, T4, T5, T6>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) {

View File

@ -38,10 +38,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4, T5, T6, T7)> ISelect<T1, T2, T3, T4, T5, T6, T7>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7)>(exp?.Body);
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) {

View File

@ -40,10 +40,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4, T5, T6, T7, T8)> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7, T8)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7, T8)>(exp?.Body);
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) {

View File

@ -42,10 +42,10 @@ namespace FreeSql.Internal.CommonProvider {
return this.InternalAvgAsync<TMember>(column?.Body);
}
ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey>(exp?.Body);
ISelectGrouping<TKey, (T1, T2, T3, T4, T5, T6, T7, T8, T9)> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TKey>> exp) {
if (exp == null) return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7, T8, T9)>(exp?.Body);
for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a];
return this.InternalGroupBy<TKey>(exp?.Body);
return this.InternalGroupBy<TKey, (T1, T2, T3, T4, T5, T6, T7, T8, T9)>(exp?.Body);
}
TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) {

View File

@ -8,48 +8,89 @@ using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
class SelectGroupingProvider<T1> : ISelectGrouping<T1> {
class SelectGroupingProvider<TKey, TValue> : ISelectGrouping<TKey, TValue> {
internal object _select;
internal ReadAnonymousTypeInfo _map;
internal CommonExpression _comonExp;
public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp) {
internal List<SelectTableInfo> _tables;
public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp, List<SelectTableInfo> tables) {
_select = select;
_map = map;
_comonExp = comonExp;
_tables = tables;
}
string getSelectGroupingMapString(Expression[] members) {
var read = _map;
for (var a = 0; a < members.Length; a++) {
read = read.Childs.Where(z => z.CsName == (members[a] as MemberExpression)?.Member.Name).FirstOrDefault();
if (read == null) return null;
if (members.Any() == false) return _map.DbField;
var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;
switch(parentName) {
case "Key":
var read = _map;
for (var a = 0; a < members.Length; a++) {
read = read.Childs.Where(z => z.CsName == (members[a] as MemberExpression)?.Member.Name).FirstOrDefault();
if (read == null) return null;
}
return read.DbField;
case "Value":
var tb = _tables.First();
var foridx = 0;
if (members.Length > 1) {
var mem0 = (members.FirstOrDefault() as MemberExpression);
var mem0Name = mem0?.Member.Name;
if (mem0Name?.StartsWith("Item") == true && int.TryParse(mem0Name.Substring(4), out var tryitemidx)) {
if (tryitemidx == 1) foridx++;
else {
var alias = $"SP10{(char)(96 + tryitemidx)}";
var tmptb = _tables.Where(a => a.AliasInit == alias && a.Table.Type == mem0.Type).FirstOrDefault();
if (tmptb != null) {
tb = tmptb;
foridx++;
}
}
}
}
var parmExp = Expression.Parameter(tb.Table.Type, tb.Alias);
Expression retExp = parmExp;
for (var a = foridx; a < members.Length; a++) {
switch(members[a].NodeType) {
case ExpressionType.Call:
retExp = Expression.Call(retExp, (members[a] as MethodCallExpression).Method);
break;
case ExpressionType.MemberAccess:
retExp = Expression.MakeMemberAccess(retExp, (members[a] as MemberExpression).Member);
break;
default:
return null;
}
}
return _comonExp.ExpressionLambdaToSql(retExp, _tables, null, null, SelectTableInfoType.From, true, true, CommonExpression.ExpressionStyle.Where);
}
return read.DbField;
return null;
}
public ISelectGrouping<T1> Having(Expression<Func<ISelectGroupingAggregate<T1>, bool>> exp) {
public ISelectGrouping<TKey, TValue> Having(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, bool>> exp) {
var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString);
var method = _select.GetType().GetMethod("Having", new[] { typeof(string), typeof(object) });
method.Invoke(_select, new object[] { sql, null });
return this;
}
public ISelectGrouping<T1> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
public ISelectGrouping<TKey, TValue> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TMember>> column) {
var sql = _comonExp.ExpressionWhereLambda(null, column, getSelectGroupingMapString);
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
method.Invoke(_select, new object[] { sql, null });
return this;
}
public ISelectGrouping<T1> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
public ISelectGrouping<TKey, TValue> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TMember>> column) {
var sql = _comonExp.ExpressionWhereLambda(null, column, getSelectGroupingMapString);
var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
method.Invoke(_select, new object[] { $"{sql} DESC", null });
return this;
}
public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) {
var map = new ReadAnonymousTypeInfo();
var field = new StringBuilder();
var index = 0;
@ -59,7 +100,7 @@ namespace FreeSql.Internal.CommonProvider {
method = method.MakeGenericMethod(typeof(TReturn));
return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List<TReturn>;
}
public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) {
var map = new ReadAnonymousTypeInfo();
var field = new StringBuilder();
var index = 0;
@ -70,7 +111,7 @@ namespace FreeSql.Internal.CommonProvider {
return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task<List<TReturn>>;
}
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) {
var map = new ReadAnonymousTypeInfo();
var field = new StringBuilder();
var index = 0;
@ -80,21 +121,21 @@ namespace FreeSql.Internal.CommonProvider {
return method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string;
}
public ISelectGrouping<T1> Skip(int offset) {
public ISelectGrouping<TKey, TValue> Skip(int offset) {
var method = _select.GetType().GetMethod("Skip", new[] { typeof(int) });
method.Invoke(_select, new object[] { offset });
return this;
}
public ISelectGrouping<T1> Offset(int offset) => this.Skip(offset);
public ISelectGrouping<TKey, TValue> Offset(int offset) => this.Skip(offset);
public ISelectGrouping<T1> Limit(int limit) {
public ISelectGrouping<TKey, TValue> Limit(int limit) {
var method = _select.GetType().GetMethod("Limit", new[] { typeof(int) });
method.Invoke(_select, new object[] { limit });
return this;
}
public ISelectGrouping<T1> Take(int limit) => this.Limit(limit);
public ISelectGrouping<TKey, TValue> Take(int limit) => this.Limit(limit);
public ISelectGrouping<T1> Page(int pageIndex, int pageSize) {
public ISelectGrouping<TKey, TValue> Page(int pageIndex, int pageSize) {
var method = _select.GetType().GetMethod("Page", new[] { typeof(int), typeof(int) });
method.Invoke(_select, new object[] { pageIndex, pageSize });
return this;