- 修复 DTO 子查询集合嵌套 bug;

This commit is contained in:
2881099 2022-05-23 17:51:37 +08:00
parent f756b56aa0
commit c30a850ad4
6 changed files with 107 additions and 57 deletions

View File

@ -297,7 +297,20 @@ namespace base_entity
users2 = fsql.Select<User1>().Where(b => b.GroupId == a.Id).ToList(b => new users2 = fsql.Select<User1>().Where(b => b.GroupId == a.Id).ToList(b => new
{ {
userid = b.Id, userid = b.Id,
username = b.Username username = b.Username,
users11 = fsql.Select<User1>().Where(c => c.GroupId == a.Id).ToList(),
users22 = fsql.Select<User1>().Where(c => c.GroupId == a.Id).ToList(c => new
{
userid = c.Id,
username = c.Username,
}),
groups11 = fsql.Select<UserGroup>().Where(c => c.Id == b.GroupId).ToList(),
groups22 = fsql.Select<UserGroup>().Where(c => c.Id == b.GroupId).ToList(c => new
{
c.Id,
c.GroupName,
username = b.Username,
})
}), }),
users3 = fsql.Select<User1>().Limit(10).ToList(), users3 = fsql.Select<User1>().Limit(10).ToList(),
users4 = fsql.Select<User1>().Limit(10).ToList(b => new users4 = fsql.Select<User1>().Limit(10).ToList(b => new
@ -317,7 +330,19 @@ namespace base_entity
users2 = fsql.Select<User1>().Where(b => b.GroupId == a.Id).ToList(b => new users2 = fsql.Select<User1>().Where(b => b.GroupId == a.Id).ToList(b => new
{ {
userid = b.Id, userid = b.Id,
username = b.Username username = b.Username,
users11 = fsql.Select<User1>().Where(c => c.GroupId == a.Id).ToList(),
users22 = fsql.Select<User1>().Where(c => c.GroupId == a.Id).ToList(c => new
{
userid = c.Id,
username = c.Username,
}),
groups11 = fsql.Select<UserGroup>().Where(c => c.Id == b.GroupId).ToList(),
groups22 = fsql.Select<UserGroup>().Where(c => c.Id == b.GroupId).ToList(c => new
{
c.Id, c.GroupName,
username = b.Username,
})
}), }),
users3 = fsql.Select<User1>().Limit(10).ToList(), users3 = fsql.Select<User1>().Limit(10).ToList(),
users4 = fsql.Select<User1>().Limit(10).ToList(b => new users4 = fsql.Select<User1>().Limit(10).ToList(b => new

View File

@ -14,6 +14,7 @@ namespace orm_vs
static IFreeSql fsql = new FreeSql.FreeSqlBuilder() static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=20") .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=20")
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=20") //.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=20")
.UseConnectionString(FreeSql.DataType.Sqlite, "data source=test1.db;max pool size=5")
.UseAutoSyncStructure(false) .UseAutoSyncStructure(false)
.UseNoneCommandParameter(true) .UseNoneCommandParameter(true)
//.UseConfigEntityFromDbFirst(true) //.UseConfigEntityFromDbFirst(true)

View File

@ -53,6 +53,10 @@
<Project>{28c6a39c-7ae7-4210-b7b0-0970216637a8}</Project> <Project>{28c6a39c-7ae7-4210-b7b0-0970216637a8}</Project>
<Name>FreeSql.Provider.MySql</Name> <Name>FreeSql.Provider.MySql</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj">
<Project>{559b6369-1868-4a06-a590-f80ba7b80a1b}</Project>
<Name>FreeSql.Provider.Sqlite</Name>
</ProjectReference>
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj"> <ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj">
<Project>{b61aac9e-59e9-4f47-bbe3-97ac24112efe}</Project> <Project>{b61aac9e-59e9-4f47-bbe3-97ac24112efe}</Project>
<Name>FreeSql.Provider.SqlServer</Name> <Name>FreeSql.Provider.SqlServer</Name>

View File

@ -786,14 +786,5 @@
<param name="that"></param> <param name="that"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
<summary>
批量注入 Repository可以参考代码自行调整
</summary>
<param name="services"></param>
<param name="globalDataFilter"></param>
<param name="assemblies"></param>
<returns></returns>
</member>
</members> </members>
</doc> </doc>

View File

@ -181,30 +181,68 @@ namespace FreeSql.Internal.CommonProvider
return methods.FirstOrDefault(); return methods.FirstOrDefault();
}); });
public List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> _SameSelectPendingShareData;
internal static ConcurrentDictionary<int, List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>> _SameSelectPendingOnlySync = new ConcurrentDictionary<int, List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>>(); internal Select0Provider SetSameSelectPendingShareData(List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> data)
internal List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> CurrentSameSelectPendingOnlySync => _SameSelectPendingOnlySync.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var trycur) ? trycur : null;
internal bool ProcessSameSelectPendingOnlySync(List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> cssps, ref string sql, ReadAnonymousTypeOtherInfo csspsod)
{ {
if (cssps != null) _SameSelectPendingShareData = data;
_SameSelectPendingShareData?.ForEach(a => _params.AddRange(a?.Item2 ?? new DbParameter[0]));
return this;
}
internal bool SameSelectPending(ref string sql, ReadAnonymousTypeOtherInfo csspsod)
{
if (_SameSelectPendingShareData != null)
{ {
if (cssps.Any() == false || cssps.Last() != null) if (_SameSelectPendingShareData.Any() == false || _SameSelectPendingShareData.Last() != null)
{ {
cssps.Add(NativeTuple.Create(sql, _params.ToArray(), csspsod)); _SameSelectPendingShareData.Add(NativeTuple.Create(sql, _params.ToArray(), csspsod));
return true; return true;
} }
cssps[cssps.Count - 1] = NativeTuple.Create(sql, _params.ToArray(), csspsod); _SameSelectPendingShareData[_SameSelectPendingShareData.Count - 1] = NativeTuple.Create(sql, _params.ToArray(), csspsod);
var sbSql = new StringBuilder(); //last == null flush flag var sbSql = new StringBuilder(); //last == null flush flag
for (var a = 0; a < cssps.Count; a++) for (var a = 0; a < _SameSelectPendingShareData.Count; a++)
sbSql.Append("\r\nUNION ALL\r\nselect * from (").Append(cssps[a].Item1).Append(") ftb"); sbSql.Append("\r\nUNION ALL\r\nselect * from (").Append(_SameSelectPendingShareData[a].Item1).Append(") ftb");
sbSql.Remove(0, 13); sbSql.Remove(0, 13);
if (cssps.Count == 1) sbSql.Remove(0, 15).Remove(sbSql.Length - 5, 5); if (_SameSelectPendingShareData.Count == 1) sbSql.Remove(0, 15).Remove(sbSql.Length - 5, 5);
sql = sbSql.ToString(); sql = sbSql.ToString();
//dbParms = cssps.Select(a => a.Item2).SelectMany(a => a).ToArray(); //dbParms = cssps.Select(a => a.Item2).SelectMany(a => a).ToArray();
sbSql.Clear(); sbSql.Clear();
} }
return false; return false;
} }
internal static Expression SetSameSelectPendingShareDataWithExpression(Expression exp, List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> data)
{
var callExp = exp as MethodCallExpression;
var callExpStack = new Stack<MethodCallExpression>();
callExpStack.Push(callExp);
callExp = callExp.Object as MethodCallExpression; //忽略第一个方法
while (callExp != null)
{
if (callExp?.Type.FullName.StartsWith("FreeSql.ISelect`") == true)
{
callExpStack.Push(callExp);
callExp = callExp.Object as MethodCallExpression;
continue;
}
return exp;
}
callExp = callExpStack.Pop();
Expression newExp = Expression.Call(
Expression.Convert(callExp, typeof(Select0Provider)),
typeof(Select0Provider).GetMethod(nameof(SetSameSelectPendingShareData), BindingFlags.NonPublic | BindingFlags.Instance),
Expression.Constant(data, typeof(List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>))
);
newExp = Expression.Convert(newExp, callExp.Type);
while (callExpStack.Any())
{
callExp = callExpStack.Pop();
newExp = Expression.Call(
newExp,
callExp.Method,
callExp.Arguments
);
}
return newExp;
}
} }
public abstract partial class Select0Provider<TSelect, T1> : Select0Provider, ISelect0<TSelect, T1> where TSelect : class public abstract partial class Select0Provider<TSelect, T1> : Select0Provider, ISelect0<TSelect, T1> where TSelect : class
@ -217,7 +255,6 @@ namespace FreeSql.Internal.CommonProvider
_tables.Add(new SelectTableInfo { Table = _commonUtils.GetTableByEntity(typeof(T1)), Alias = "a", On = null, Type = SelectTableInfoType.From }); _tables.Add(new SelectTableInfo { Table = _commonUtils.GetTableByEntity(typeof(T1)), Alias = "a", On = null, Type = SelectTableInfoType.From });
this.Where(_commonUtils.WhereObject(_tables.First().Table, "a.", dywhere)); this.Where(_commonUtils.WhereObject(_tables.First().Table, "a.", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>(); if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
CurrentSameSelectPendingOnlySync?.ForEach(a => _params.AddRange(a?.Item2 ?? new DbParameter[0]));
} }
public TSelect TrackToList(Action<object> track) public TSelect TrackToList(Action<object> track)

View File

@ -139,13 +139,12 @@ namespace FreeSql.Internal.CommonProvider
} }
internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData) internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData)
{ {
var cssps = CurrentSameSelectPendingOnlySync;
ReadAnonymousTypeOtherInfo csspsod = null; ReadAnonymousTypeOtherInfo csspsod = null;
if (cssps != null) if (_SameSelectPendingShareData != null)
{ {
var ods = new List<ReadAnonymousTypeOtherInfo>(); var ods = new List<ReadAnonymousTypeOtherInfo>();
if (otherData?.Any() == true) ods.AddRange(otherData); if (otherData?.Any() == true) ods.AddRange(otherData);
ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(cssps.Any() && cssps.Last() == null ? cssps.Count - 1 : cssps.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>())); ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(_SameSelectPendingShareData.Any() && _SameSelectPendingShareData.Last() == null ? _SameSelectPendingShareData.Count - 1 : _SameSelectPendingShareData.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>()));
otherData = ods.ToArray(); otherData = ods.ToArray();
} }
@ -160,7 +159,7 @@ namespace FreeSql.Internal.CommonProvider
else else
sql = this.ToSql(af.Field); sql = this.ToSql(af.Field);
if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return new List<T1>(); if (SameSelectPending(ref sql, csspsod)) return new List<T1>();
return ToListAfPrivate(sql, af, otherData); return ToListAfPrivate(sql, af, otherData);
} }
#region ToChunk #region ToChunk
@ -371,13 +370,12 @@ namespace FreeSql.Internal.CommonProvider
} }
internal List<TReturn> ToListMapReaderPrivate<TReturn>(ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData) internal List<TReturn> ToListMapReaderPrivate<TReturn>(ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData)
{ {
var cssps = CurrentSameSelectPendingOnlySync;
ReadAnonymousTypeOtherInfo csspsod = null; ReadAnonymousTypeOtherInfo csspsod = null;
if (cssps != null) if (_SameSelectPendingShareData != null)
{ {
var ods = new List<ReadAnonymousTypeOtherInfo>(); var ods = new List<ReadAnonymousTypeOtherInfo>();
if (otherData?.Any() == true) ods.AddRange(otherData); if (otherData?.Any() == true) ods.AddRange(otherData);
ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(cssps.Any() && cssps.Last() == null ? cssps.Count - 1 : cssps.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>())); ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(_SameSelectPendingShareData.Any() && _SameSelectPendingShareData.Last() == null ? _SameSelectPendingShareData.Count - 1 : _SameSelectPendingShareData.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>()));
otherData = ods.ToArray(); otherData = ods.ToArray();
} }
@ -392,7 +390,7 @@ namespace FreeSql.Internal.CommonProvider
else else
sql = this.ToSql(af.field); sql = this.ToSql(af.field);
if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return new List<TReturn>(); if (SameSelectPending(ref sql, csspsod)) return new List<TReturn>();
return ToListMrPrivate<TReturn>(sql, af, otherData); return ToListMrPrivate<TReturn>(sql, af, otherData);
} }
protected List<TReturn> ToListMapReader<TReturn>(ReadAnonymousTypeAfInfo af) => ToListMapReaderPrivate<TReturn>(af, null); protected List<TReturn> ToListMapReader<TReturn>(ReadAnonymousTypeAfInfo af) => ToListMapReaderPrivate<TReturn>(af, null);
@ -944,11 +942,9 @@ namespace FreeSql.Internal.CommonProvider
af.fillSubSelectMany[b].Item2.Add(otherListItem); af.fillSubSelectMany[b].Item2.Add(otherListItem);
continue; continue;
} }
var threadId = Thread.CurrentThread.ManagedThreadId; var sspShareData = new List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>();
try try
{ {
_SameSelectPendingOnlySync.TryAdd(threadId, new List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>());
var cssps = CurrentSameSelectPendingOnlySync;
var newexp = findSubSelectMany[a]; var newexp = findSubSelectMany[a];
var newexpParms = otherAfmanys[a].Select(d => var newexpParms = otherAfmanys[a].Select(d =>
{ {
@ -956,35 +952,35 @@ namespace FreeSql.Internal.CommonProvider
newexp = rmev.Replace(newexp, d.Item1, newexpParm); newexp = rmev.Replace(newexp, d.Item1, newexpParm);
return newexpParm; return newexpParm;
}).ToArray(); }).ToArray();
newexp = SetSameSelectPendingShareDataWithExpression(newexp, sspShareData);
var newexpFunc = Expression.Lambda(newexp, newexpParms).Compile(); var newexpFunc = Expression.Lambda(newexp, newexpParms).Compile();
var newexpParamVals = otherAfmanys[a].Select(d => otherAfdic[d.Item1.ToString()].First().Item3.retlist).ToArray(); var newexpParamVals = otherAfmanys[a].Select(d => otherAfdic[d.Item1.ToString()].First().Item3.retlist).ToArray();
for (int b = a, c = 0; b < af.fillSubSelectMany?.Count; b += otherAfmanys.Count, c++) for (int b = a, c = 0; b < af.fillSubSelectMany?.Count; b += otherAfmanys.Count, c++)
{ {
var vals = newexpParamVals.Select(d => d[c]).ToArray(); var vals = newexpParamVals.Select(d => d[c]).ToArray();
if (c == ret.Count - 1) cssps.Add(null); //flush flag if (c == ret.Count - 1) sspShareData.Add(null); //flush flag
var diret = newexpFunc.DynamicInvoke(vals); var diret = newexpFunc.DynamicInvoke(vals);
if (c < ret.Count - 1) continue; if (c < ret.Count - 1) continue;
var otherList = diret as IEnumerable; var otherList = diret as IEnumerable;
var retlistidx = 0; var retlistidx = 0;
foreach (var otherListItem in otherList) foreach (var otherListItem in otherList)
{ {
var retlist = cssps[0].Item3.retlist; var retlist = sspShareData[0].Item3.retlist;
while (retlistidx >= retlist.Count) while (retlistidx >= retlist.Count)
{ {
cssps.RemoveAt(0); sspShareData.RemoveAt(0);
retlist = cssps[0].Item3.retlist; retlist = sspShareData[0].Item3.retlist;
retlistidx = 0; retlistidx = 0;
} }
int.TryParse(retlist[retlistidx++]?.ToString(), out var tryrowidx); int.TryParse(retlist[retlistidx++]?.ToString(), out var tryrowidx);
af.fillSubSelectMany[tryrowidx * otherAfmanys.Count + a].Item2.Add(otherListItem); af.fillSubSelectMany[tryrowidx * otherAfmanys.Count + a].Item2.Add(otherListItem);
} }
} }
cssps.Clear();
} }
finally finally
{ {
_SameSelectPendingOnlySync.TryRemove(threadId, out var oldssps); sspShareData.Clear();
} }
} }
return ret; return ret;
@ -1225,13 +1221,12 @@ namespace FreeSql.Internal.CommonProvider
internal Task<List<T1>> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken) internal Task<List<T1>> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken)
{ {
var cssps = CurrentSameSelectPendingOnlySync;
ReadAnonymousTypeOtherInfo csspsod = null; ReadAnonymousTypeOtherInfo csspsod = null;
if (cssps != null) if (_SameSelectPendingShareData != null)
{ {
var ods = new List<ReadAnonymousTypeOtherInfo>(); var ods = new List<ReadAnonymousTypeOtherInfo>();
if (otherData?.Any() == true) ods.AddRange(otherData); if (otherData?.Any() == true) ods.AddRange(otherData);
ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(cssps.Any() && cssps.Last() == null ? cssps.Count - 1 : cssps.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>())); ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(_SameSelectPendingShareData.Any() && _SameSelectPendingShareData.Last() == null ? _SameSelectPendingShareData.Count - 1 : _SameSelectPendingShareData.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>()));
otherData = ods.ToArray(); otherData = ods.ToArray();
} }
@ -1246,7 +1241,7 @@ namespace FreeSql.Internal.CommonProvider
else else
sql = this.ToSql(af.Field); sql = this.ToSql(af.Field);
if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return Task.FromResult(new List<T1>()); if (SameSelectPending(ref sql, csspsod)) return Task.FromResult(new List<T1>());
return ToListAfPrivateAsync(sql, af, otherData, cancellationToken); return ToListAfPrivateAsync(sql, af, otherData, cancellationToken);
} }
@ -1327,13 +1322,12 @@ namespace FreeSql.Internal.CommonProvider
} }
internal Task<List<TReturn>> ToListMapReaderPrivateAsync<TReturn>(ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken) internal Task<List<TReturn>> ToListMapReaderPrivateAsync<TReturn>(ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken)
{ {
var cssps = CurrentSameSelectPendingOnlySync;
ReadAnonymousTypeOtherInfo csspsod = null; ReadAnonymousTypeOtherInfo csspsod = null;
if (cssps != null) if (_SameSelectPendingShareData != null)
{ {
var ods = new List<ReadAnonymousTypeOtherInfo>(); var ods = new List<ReadAnonymousTypeOtherInfo>();
if (otherData?.Any() == true) ods.AddRange(otherData); if (otherData?.Any() == true) ods.AddRange(otherData);
ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(cssps.Any() && cssps.Last() == null ? cssps.Count - 1 : cssps.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>())); ods.Add(csspsod = new ReadAnonymousTypeOtherInfo($", {(_SameSelectPendingShareData.Any() && _SameSelectPendingShareData.Last() == null ? _SameSelectPendingShareData.Count - 1 : _SameSelectPendingShareData.Count)}{_commonUtils.FieldAsAlias("fsql_subsel_rowidx")}", new ReadAnonymousTypeInfo { CsType = typeof(int) }, new List<object>()));
otherData = ods.ToArray(); otherData = ods.ToArray();
} }
@ -1348,7 +1342,7 @@ namespace FreeSql.Internal.CommonProvider
else else
sql = this.ToSql(af.field); sql = this.ToSql(af.field);
if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return Task.FromResult(new List<TReturn>()); if (SameSelectPending(ref sql, csspsod)) return Task.FromResult(new List<TReturn>());
return ToListMrPrivateAsync<TReturn>(sql, af, otherData, cancellationToken); return ToListMrPrivateAsync<TReturn>(sql, af, otherData, cancellationToken);
} }
protected Task<List<TReturn>> ToListMapReaderAsync<TReturn>(ReadAnonymousTypeAfInfo af, CancellationToken cancellationToken) => ToListMapReaderPrivateAsync<TReturn>(af, null, cancellationToken); protected Task<List<TReturn>> ToListMapReaderAsync<TReturn>(ReadAnonymousTypeAfInfo af, CancellationToken cancellationToken) => ToListMapReaderPrivateAsync<TReturn>(af, null, cancellationToken);
@ -1412,11 +1406,9 @@ namespace FreeSql.Internal.CommonProvider
af.fillSubSelectMany[b].Item2.Add(otherListItem); af.fillSubSelectMany[b].Item2.Add(otherListItem);
continue; continue;
} }
var threadId = Thread.CurrentThread.ManagedThreadId; //一定要【注意】 await 会影响该值,以下以容将 ToList 替换成 ToListAsync 后再执行 var sspShareData = new List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>();
try try
{ {
_SameSelectPendingOnlySync.TryAdd(threadId, new List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>>());
var cssps = CurrentSameSelectPendingOnlySync;
var newexp = findSubSelectMany[a]; var newexp = findSubSelectMany[a];
var newexpParms = otherAfmanys[a].Select(d => var newexpParms = otherAfmanys[a].Select(d =>
{ {
@ -1450,13 +1442,14 @@ namespace FreeSql.Internal.CommonProvider
if (asyncMethod != null) if (asyncMethod != null)
newexp = Expression.Call(newexpCallExp.Object, asyncMethod, newexpCallExp.Arguments.Concat(new[] { Expression.Constant(cancellationToken, typeof(CancellationToken)) }).ToArray()); newexp = Expression.Call(newexpCallExp.Object, asyncMethod, newexpCallExp.Arguments.Concat(new[] { Expression.Constant(cancellationToken, typeof(CancellationToken)) }).ToArray());
} }
newexp = SetSameSelectPendingShareDataWithExpression(newexp, sspShareData);
var newexpFunc = Expression.Lambda(newexp, newexpParms).Compile(); var newexpFunc = Expression.Lambda(newexp, newexpParms).Compile();
var newexpParamVals = otherAfmanys[a].Select(d => otherAfdic[d.Item1.ToString()].First().Item3.retlist).ToArray(); var newexpParamVals = otherAfmanys[a].Select(d => otherAfdic[d.Item1.ToString()].First().Item3.retlist).ToArray();
for (int b = a, c = 0; b < af.fillSubSelectMany?.Count; b += otherAfmanys.Count, c++) for (int b = a, c = 0; b < af.fillSubSelectMany?.Count; b += otherAfmanys.Count, c++)
{ {
var vals = newexpParamVals.Select(d => d[c]).ToArray(); var vals = newexpParamVals.Select(d => d[c]).ToArray();
if (c == ret.Count - 1) cssps.Add(null); //flush flag if (c == ret.Count - 1) sspShareData.Add(null); //flush flag
var diretTask = newexpFunc.DynamicInvoke(vals) as Task; var diretTask = newexpFunc.DynamicInvoke(vals) as Task;
if (c < ret.Count - 1) continue; if (c < ret.Count - 1) continue;
@ -1466,22 +1459,21 @@ namespace FreeSql.Internal.CommonProvider
var retlistidx = 0; var retlistidx = 0;
foreach (var otherListItem in otherList) foreach (var otherListItem in otherList)
{ {
var retlist = cssps[0].Item3.retlist; var retlist = sspShareData[0].Item3.retlist;
while (retlistidx >= retlist.Count) while (retlistidx >= retlist.Count)
{ {
cssps.RemoveAt(0); sspShareData.RemoveAt(0);
retlist = cssps[0].Item3.retlist; retlist = sspShareData[0].Item3.retlist;
retlistidx = 0; retlistidx = 0;
} }
int.TryParse(retlist[retlistidx++]?.ToString(), out var tryrowidx); int.TryParse(retlist[retlistidx++]?.ToString(), out var tryrowidx);
af.fillSubSelectMany[tryrowidx * otherAfmanys.Count + a].Item2.Add(otherListItem); af.fillSubSelectMany[tryrowidx * otherAfmanys.Count + a].Item2.Add(otherListItem);
} }
} }
cssps.Clear();
} }
finally finally
{ {
_SameSelectPendingOnlySync.TryRemove(threadId, out var oldssps); sspShareData.Clear();
} }
} }
return ret; return ret;