From 27cb11e4a7907a7e0f5c4a380036600b199fda55 Mon Sep 17 00:00:00 2001
From: 2881099 <2881099@qq.com>
Date: Wed, 25 May 2022 01:14:27 +0800
Subject: [PATCH] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20Limit=20+=20Sum/Avg/Ma?=
=?UTF-8?q?x/Min=20=E4=B8=BA=E5=B5=8C=E5=A5=97=E6=9F=A5=E8=AF=A2=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Directory.Build.props | 2 +-
.../Sqlite/Curd/SqliteSelectTest.cs | 9 +-
FreeSql/Internal/CommonExpression.cs | 10 +-
.../SelectProvider/Select0Provider.cs | 107 +++++++++
.../SelectProvider/Select0ProviderReader.cs | 220 ++++++------------
5 files changed, 199 insertions(+), 149 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 03a940e9..14935b0e 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -9,7 +9,7 @@
- 3.2.651
+ 3.2.660-preview22020525
diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
index c438ae01..2e1300c0 100644
--- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
@@ -1001,10 +1001,15 @@ limit 0,10", t1);
var subquery = select.ToSql(a => new
{
all = a,
- count = (long)select.As("b").Sum(b => b.Id)
+ count = (long)select.As("b").Sum(b => b.Id),
+ sum2 = (long)select.As("b").Limit(10).Sum(b => b.Id)
});
Assert.Equal(@"SELECT a.""Id"" as1, a.""Clicks"" as2, a.""TypeGuid"" as3, a.""Title"" as4, a.""CreateTime"" as5, ifnull((SELECT sum(b.""Id"")
- FROM ""tb_topic22"" b), 0) as6
+ FROM ""tb_topic22"" b), 0) as6, ifnull((SELECT sum(ftba.""Id"") FROM (
+ SELECT b.""Id""
+ FROM ""tb_topic22"" b
+ limit 0,10
+) ftba), 0) as7
FROM ""tb_topic22"" a", subquery);
var subqueryList = select.ToList(a => new
{
diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs
index c9b60954..72815953 100644
--- a/FreeSql/Internal/CommonExpression.cs
+++ b/FreeSql/Internal/CommonExpression.cs
@@ -1362,9 +1362,15 @@ namespace FreeSql.Internal
var exp3Args0 = (exp3.Arguments.FirstOrDefault() as UnaryExpression)?.Operand as LambdaExpression;
if (exp3Args0.Parameters.Count == 1 && exp3Args0.Parameters[0].Type.FullName.StartsWith("FreeSql.Internal.Model.HzyTuple`"))
exp3Args0 = new ReplaceHzyTupleToMultiParam().Modify(exp3Args0, fsqltables);
- var sqlSum = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { $"{exp3.Method.Name.ToLower()}({ExpressionLambdaToSql(exp3Args0, tscClone1)})" })?.ToString();
+ var sqlSumField = $"{exp3.Method.Name.ToLower()}({ExpressionLambdaToSql(exp3Args0, tscClone1)})";
+ var sqlSum = tscClone1.subSelect001._limit <= 0 && tscClone1.subSelect001._skip <= 0 ?
+ fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { $"{exp3.Method.Name.ToLower()}({ExpressionLambdaToSql(exp3Args0, tscClone1)})" })?.ToString() :
+ tscClone1.subSelect001.GetNestSelectSql(exp3Args0, sqlSumField, tosqlField =>
+ fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { tosqlField })?.ToString());
if (string.IsNullOrEmpty(sqlSum) == false)
- return _common.IsNull($"({sqlSum.Replace(" \r\n", " \r\n ")})", 0);
+ return tscClone1.subSelect001._limit <= 0 && tscClone1.subSelect001._skip <= 0 ?
+ _common.IsNull($"({sqlSum.Replace(" \r\n", " \r\n ")})", 0) :
+ _common.IsNull($"({sqlSum})", 0);
break;
case "ToList":
case "ToOne":
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
index 308f0353..5b4f2268 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
@@ -243,6 +243,113 @@ namespace FreeSql.Internal.CommonProvider
}
return newExp;
}
+
+ public ReadAnonymousTypeAfInfo GetExpressionField(Expression newexp, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
+ {
+ var map = new ReadAnonymousTypeInfo();
+ var field = new StringBuilder();
+ var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0;
+
+ _commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, this, null, _whereGlobalFilter, null, null, true);
+ return new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null);
+ }
+ public string GetNestSelectSql(Expression select, string affield, Func ToSql)
+ {
+ var allMemExps = new FindAllMemberExpressionVisitor(this);
+ allMemExps.Visit(select);
+ var fieldAlias = new Dictionary();
+ var fieldReplaced = new Dictionary();
+ var field = new StringBuilder();
+ foreach (var memExp in allMemExps.Result)
+ {
+ var gef = GetExpressionField(memExp.Item1, FieldAliasOptions.AsProperty);
+ var geffield = gef.field;
+ if (fieldReplaced.ContainsKey(geffield)) continue;
+ fieldReplaced.Add(geffield, true);
+
+ field.Append(", ").Append(gef.field);
+ if (fieldAlias.ContainsKey(memExp.Item2.Attribute.Name))
+ {
+ field.Append(_commonUtils.FieldAsAlias($"aas{fieldAlias.Count}"));
+ affield = affield.Replace(geffield, $"ftba.aas{fieldAlias.Count}");
+ }
+ else
+ {
+ fieldAlias.Add(memExp.Item2.Attribute.Name, true);
+ affield = affield.Replace(geffield, $"ftba.{string.Join(".", geffield.Split('.').Skip(1))}");
+ }
+ }
+
+ var sql = ToSql(field.Remove(0, 2).ToString());
+ sql = $"{_select} {affield} FROM ( \r\n {sql.Replace("\r\n", "\r\n ")}\r\n) ftba";
+ field.Clear();
+ return sql;
+ }
+ public class FindAllMemberExpressionVisitor : ExpressionVisitor
+ {
+ public List> Result { get; set; } = new List>();
+ Select0Provider _select;
+ public FindAllMemberExpressionVisitor(Select0Provider select) => _select = select;
+
+ protected override Expression VisitMember(MemberExpression node)
+ {
+ var exps = new Stack();
+ Expression exp = node;
+ while (exp != null)
+ {
+ switch (exp.NodeType)
+ {
+ case ExpressionType.Parameter:
+ exps.Push(exp);
+ exp = null;
+ continue;
+ case ExpressionType.MemberAccess:
+ exps.Push(exp);
+ exp = (exp as MemberExpression)?.Expression;
+ continue;
+ }
+ return base.VisitMember(node);
+ }
+ if (exps.Any() == false) return base.VisitMember(node);
+ var firstExp = exps.Pop() as ParameterExpression;
+ if (firstExp == null) return base.VisitMember(node);
+ var tb = _select._tables.Find(a => a.Parameter == firstExp)?.Table;
+ if (tb == null) return base.VisitMember(node);
+
+ while (exps.Any())
+ {
+ var memExp = exps.Pop() as MemberExpression;
+ if (tb.ColumnsByCs.TryGetValue(memExp.Member.Name, out var trycol) && exps.Any() == false)
+ {
+ Result.Add(NativeTuple.Create(node, trycol));
+ return node;
+ }
+ if (tb.Properties.ContainsKey(memExp.Member.Name))
+ {
+ tb = _select._commonUtils.GetTableByEntity(memExp.Type);
+ if (tb == null) return base.VisitMember(node);
+ }
+ }
+ return base.VisitMember(node);
+ }
+ }
+ public class ReplaceMemberExpressionVisitor : ExpressionVisitor
+ {
+ Expression _findExp;
+ Expression _replaceExp;
+ public Expression Replace(Expression exp, Expression find, Expression replace) // object repval)
+ {
+ _findExp = find;
+ _replaceExp = replace;
+ //_replaceExp = Expression.Constant(repval, find.Type);
+ return this.Visit(exp);
+ }
+ protected override Expression VisitMember(MemberExpression node)
+ {
+ if (_findExp == node) return _replaceExp;
+ return base.VisitMember(node);
+ }
+ }
}
public abstract partial class Select0Provider : Select0Provider, ISelect0 where TSelect : class
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs
index 12988a7b..9af516b6 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs
@@ -64,11 +64,12 @@ namespace FreeSql.Internal.CommonProvider
return ret;
}
- public List ToList(string field)
+ public List ToList(string field) => ToListQfPrivate(this.ToSql(field), field);
+ public List ToListQfPrivate(string sql, string field)
{
var ret = new List();
if (_cancel?.Invoke() == true) return ret;
- var sql = this.ToSql(field);
+ if (string.IsNullOrEmpty(sql)) return ret;
var dbParms = _params.ToArray();
var type = typeof(TTuple);
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
@@ -394,15 +395,6 @@ namespace FreeSql.Internal.CommonProvider
return ToListMrPrivate(sql, af, otherData);
}
protected List ToListMapReader(ReadAnonymousTypeAfInfo af) => ToListMapReaderPrivate(af, null);
- protected ReadAnonymousTypeAfInfo GetExpressionField(Expression newexp, FieldAliasOptions fieldAlias = FieldAliasOptions.AsIndex)
- {
- var map = new ReadAnonymousTypeInfo();
- var field = new StringBuilder();
- var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0;
-
- _commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, this, null, _whereGlobalFilter, null, null, true);
- return new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null);
- }
static ConcurrentDictionary _dicGetAllFieldExpressionTree = new ConcurrentDictionary();
public class GetAllFieldExpressionTreeInfo
{
@@ -771,12 +763,41 @@ namespace FreeSql.Internal.CommonProvider
protected double InternalAvg(Expression exp)
{
- var list = this.ToList($"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}");
- return list.Sum() / list.Count;
+ var field = $"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0)
+ {
+ var list = this.ToList(field);
+ return list.Sum() / list.Count;
+ }
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ var list2 = ToListQfPrivate(sql, field);
+ return list2.Sum() / list2.Count;
+ }
+ protected TMember InternalMax(Expression exp)
+ {
+ var field = $"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0) return this.ToList(field).Max();
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ return ToListQfPrivate(sql, field).Max();
+ }
+ protected TMember InternalMin(Expression exp)
+ {
+ var field = $"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0) return this.ToList(field).Min();
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ return ToListQfPrivate(sql, field).Min();
+ }
+ protected decimal InternalSum(Expression exp)
+ {
+ var field = $"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0) return this.ToList(field).Sum();
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ return ToListQfPrivate(sql, field).Sum();
}
- protected TMember InternalMax(Expression exp) => this.ToList($"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Max();
- protected TMember InternalMin(Expression exp) => this.ToList($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Min();
- protected decimal InternalSum(Expression exp) => this.ToList($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}").Sum();
public ISelectGrouping InternalGroupBy(Expression columns)
{
@@ -829,71 +850,6 @@ namespace FreeSql.Internal.CommonProvider
return this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
}
- class FindAllMemberExpressionVisitor : ExpressionVisitor
- {
- public List> Result { get; set; } = new List>();
- Select0Provider _select;
- public FindAllMemberExpressionVisitor(Select0Provider select) => _select = select;
-
- protected override Expression VisitMember(MemberExpression node)
- {
- var exps = new Stack();
- Expression exp = node;
- while (exp != null)
- {
- switch (exp.NodeType)
- {
- case ExpressionType.Parameter:
- exps.Push(exp);
- exp = null;
- continue;
- case ExpressionType.MemberAccess:
- exps.Push(exp);
- exp = (exp as MemberExpression)?.Expression;
- continue;
- }
- return base.VisitMember(node);
- }
- if (exps.Any() == false) return base.VisitMember(node);
- var firstExp = exps.Pop() as ParameterExpression;
- if (firstExp == null) return base.VisitMember(node);
- var tb = _select._tables.Find(a => a.Parameter == firstExp)?.Table;
- if (tb == null) return base.VisitMember(node);
-
- while (exps.Any())
- {
- var memExp = exps.Pop() as MemberExpression;
- if (tb.ColumnsByCs.TryGetValue(memExp.Member.Name, out var trycol) && exps.Any() == false)
- {
- Result.Add(NativeTuple.Create(node, trycol));
- return node;
- }
- if (tb.Properties.ContainsKey(memExp.Member.Name))
- {
- tb = _select._commonUtils.GetTableByEntity(memExp.Type);
- if (tb == null) return base.VisitMember(node);
- }
- }
- return base.VisitMember(node);
- }
- }
- class ReplaceMemberExpressionVisitor : ExpressionVisitor
- {
- Expression _findExp;
- Expression _replaceExp;
- public Expression Replace(Expression exp, Expression find, Expression replace) // object repval)
- {
- _findExp = find;
- _replaceExp = replace;
- //_replaceExp = Expression.Constant(repval, find.Type);
- return this.Visit(exp);
- }
- protected override Expression VisitMember(MemberExpression node)
- {
- if (_findExp == node) return _replaceExp;
- return base.VisitMember(node);
- }
- }
public List InternalToList(Expression select)
{
var map = new ReadAnonymousTypeInfo();
@@ -1087,34 +1043,7 @@ namespace FreeSql.Internal.CommonProvider
var af = new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null);
if (GetTableRuleUnions().Count <= 1) return this.ToListMapReader(af).FirstOrDefault();
- var affield = af.field;
- var allMemExps = new FindAllMemberExpressionVisitor(this);
- allMemExps.Visit(select);
- field.Clear();
- var fieldAlias = new Dictionary();
- var fieldReplaced = new Dictionary();
- foreach (var memExp in allMemExps.Result)
- {
- var gef = GetExpressionField(memExp.Item1, FieldAliasOptions.AsProperty);
- var geffield = gef.field;
- if (fieldReplaced.ContainsKey(geffield)) continue;
- fieldReplaced.Add(geffield, true);
-
- field.Append(", ").Append(gef.field);
- if (fieldAlias.ContainsKey(memExp.Item2.Attribute.Name))
- {
- field.Append(_commonUtils.FieldAsAlias($"aas{fieldAlias.Count}"));
- affield = affield.Replace(geffield, $"ftba.aas{fieldAlias.Count}");
- }
- else
- {
- fieldAlias.Add(memExp.Item2.Attribute.Name, true);
- affield = affield.Replace(geffield, $"ftba.{string.Join(".", geffield.Split('.').Skip(1))}");
- }
- }
-
- var sql = this.ToSql(field.Remove(0, 2).ToString());
- sql = $"{_select} {affield} FROM ( \r\n {sql.Replace("\r\n", "\r\n ")}\r\n) ftba";
+ var sql = GetNestSelectSql(select, af.field, ToSql);
return ToListMrPrivate(sql, af, null).FirstOrDefault();
}
finally
@@ -1173,11 +1102,12 @@ namespace FreeSql.Internal.CommonProvider
return ret;
}
- async public Task> ToListAsync(string field, CancellationToken cancellationToken)
+ public Task> ToListAsync(string field, CancellationToken cancellationToken) => ToListQfPrivateAsync(this.ToSql(field), field, cancellationToken);
+ async public Task> ToListQfPrivateAsync(string sql, string field, CancellationToken cancellationToken)
{
var ret = new List();
if (_cancel?.Invoke() == true) return ret;
- var sql = this.ToSql(field);
+ if (string.IsNullOrEmpty(sql)) return ret;
var dbParms = _params.ToArray();
var type = typeof(TTuple);
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
@@ -1380,12 +1310,41 @@ namespace FreeSql.Internal.CommonProvider
async protected Task InternalAvgAsync(Expression exp, CancellationToken cancellationToken)
{
- var list = await this.ToListAsync($"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}", cancellationToken);
- return list.Sum() / list.Count;
+ var field = $"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0)
+ {
+ var list = await this.ToListAsync(field, cancellationToken);
+ return list.Sum() / list.Count;
+ }
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ var list2 = await ToListQfPrivateAsync(sql, field, cancellationToken);
+ return list2.Sum() / list2.Count;
+ }
+ async protected Task InternalMaxAsync(Expression exp, CancellationToken cancellationToken)
+ {
+ var field = $"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0) return (await this.ToListAsync(field, cancellationToken)).Max();
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ return (await ToListQfPrivateAsync(sql, field, cancellationToken)).Max();
+ }
+ async protected Task InternalMinAsync(Expression exp, CancellationToken cancellationToken)
+ {
+ var field = $"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0) return (await this.ToListAsync(field, cancellationToken)).Min();
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ return (await ToListQfPrivateAsync(sql, field, cancellationToken)).Min();
+ }
+ async protected Task InternalSumAsync(Expression exp, CancellationToken cancellationToken)
+ {
+ var field = $"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}";
+ if (_limit <= 0 && _skip <= 0) return (await this.ToListAsync(field, cancellationToken)).Sum();
+
+ var sql = GetNestSelectSql(exp, field, ToSql);
+ return (await ToListQfPrivateAsync(sql, field, cancellationToken)).Sum();
}
- async protected Task InternalMaxAsync(Expression exp, CancellationToken cancellationToken) => (await this.ToListAsync($"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}", cancellationToken)).Max();
- async protected Task InternalMinAsync(Expression exp, CancellationToken cancellationToken) => (await this.ToListAsync($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}", cancellationToken)).Min();
- async protected Task InternalSumAsync(Expression exp, CancellationToken cancellationToken) => (await this.ToListAsync($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)}){_commonUtils.FieldAsAlias("as1")}", cancellationToken)).Sum();
static ConcurrentDictionary _dicGetMethodsByName = new ConcurrentDictionary();
async protected Task> InternalToListAsync(Expression select, CancellationToken cancellationToken)
@@ -1577,34 +1536,7 @@ namespace FreeSql.Internal.CommonProvider
var af = new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null);
if (GetTableRuleUnions().Count <= 1) return (await this.ToListMapReaderAsync(af, cancellationToken)).FirstOrDefault();
- var affield = af.field;
- var allMemExps = new FindAllMemberExpressionVisitor(this);
- allMemExps.Visit(select);
- field.Clear();
- var fieldAlias = new Dictionary();
- var fieldReplaced = new Dictionary();
- foreach (var memExp in allMemExps.Result)
- {
- var gef = GetExpressionField(memExp.Item1, FieldAliasOptions.AsProperty);
- var geffield = gef.field;
- if (fieldReplaced.ContainsKey(geffield)) continue;
- fieldReplaced.Add(geffield, true);
-
- field.Append(", ").Append(gef.field);
- if (fieldAlias.ContainsKey(memExp.Item2.Attribute.Name))
- {
- field.Append(_commonUtils.FieldAsAlias($"aas{fieldAlias.Count}"));
- affield = affield.Replace(geffield, $"ftba.aas{fieldAlias.Count}");
- }
- else
- {
- fieldAlias.Add(memExp.Item2.Attribute.Name, true);
- affield = affield.Replace(geffield, $"ftba.{string.Join(".", geffield.Split('.').Skip(1))}");
- }
- }
-
- var sql = this.ToSql(field.Remove(0, 2).ToString());
- sql = $"{_select} {affield} FROM ( \r\n {sql.Replace("\r\n", "\r\n ")}\r\n) ftba";
+ var sql = GetNestSelectSql(select, af.field, ToSql);
return (await ToListMrPrivateAsync(sql, af, null, cancellationToken)).FirstOrDefault();
}
finally