From c30a850ad45dc95e4d52fc3c565c29599f992927 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Mon, 23 May 2022 17:51:37 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20DTO=20=E5=AD=90?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E9=9B=86=E5=90=88=E5=B5=8C=E5=A5=97=20bug?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 29 ++++++++- Examples/orm_vs_net40/Program.cs | 1 + Examples/orm_vs_net40/orm_vs_net40.csproj | 4 ++ FreeSql.DbContext/FreeSql.DbContext.xml | 9 --- .../SelectProvider/Select0Provider.cs | 61 +++++++++++++++---- .../SelectProvider/Select0ProviderReader.cs | 60 ++++++++---------- 6 files changed, 107 insertions(+), 57 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index f28e9085..54ceec11 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -297,7 +297,20 @@ namespace base_entity users2 = fsql.Select().Where(b => b.GroupId == a.Id).ToList(b => new { userid = b.Id, - username = b.Username + username = b.Username, + users11 = fsql.Select().Where(c => c.GroupId == a.Id).ToList(), + users22 = fsql.Select().Where(c => c.GroupId == a.Id).ToList(c => new + { + userid = c.Id, + username = c.Username, + }), + groups11 = fsql.Select().Where(c => c.Id == b.GroupId).ToList(), + groups22 = fsql.Select().Where(c => c.Id == b.GroupId).ToList(c => new + { + c.Id, + c.GroupName, + username = b.Username, + }) }), users3 = fsql.Select().Limit(10).ToList(), users4 = fsql.Select().Limit(10).ToList(b => new @@ -317,7 +330,19 @@ namespace base_entity users2 = fsql.Select().Where(b => b.GroupId == a.Id).ToList(b => new { userid = b.Id, - username = b.Username + username = b.Username, + users11 = fsql.Select().Where(c => c.GroupId == a.Id).ToList(), + users22 = fsql.Select().Where(c => c.GroupId == a.Id).ToList(c => new + { + userid = c.Id, + username = c.Username, + }), + groups11 = fsql.Select().Where(c => c.Id == b.GroupId).ToList(), + groups22 = fsql.Select().Where(c => c.Id == b.GroupId).ToList(c => new + { + c.Id, c.GroupName, + username = b.Username, + }) }), users3 = fsql.Select().Limit(10).ToList(), users4 = fsql.Select().Limit(10).ToList(b => new diff --git a/Examples/orm_vs_net40/Program.cs b/Examples/orm_vs_net40/Program.cs index 6e080b94..43216fbc 100644 --- a/Examples/orm_vs_net40/Program.cs +++ b/Examples/orm_vs_net40/Program.cs @@ -14,6 +14,7 @@ namespace orm_vs 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.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) .UseNoneCommandParameter(true) //.UseConfigEntityFromDbFirst(true) diff --git a/Examples/orm_vs_net40/orm_vs_net40.csproj b/Examples/orm_vs_net40/orm_vs_net40.csproj index b26d2626..4d3dbd14 100644 --- a/Examples/orm_vs_net40/orm_vs_net40.csproj +++ b/Examples/orm_vs_net40/orm_vs_net40.csproj @@ -53,6 +53,10 @@ {28c6a39c-7ae7-4210-b7b0-0970216637a8} FreeSql.Provider.MySql + + {559b6369-1868-4a06-a590-f80ba7b80a1b} + FreeSql.Provider.Sqlite + {b61aac9e-59e9-4f47-bbe3-97ac24112efe} FreeSql.Provider.SqlServer diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index d34b34ef..4335acb5 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -786,14 +786,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 2ed9ffa2..308f0353 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -181,30 +181,68 @@ namespace FreeSql.Internal.CommonProvider return methods.FirstOrDefault(); }); - - internal static ConcurrentDictionary>> _SameSelectPendingOnlySync = new ConcurrentDictionary>>(); - internal List> CurrentSameSelectPendingOnlySync => _SameSelectPendingOnlySync.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var trycur) ? trycur : null; - internal bool ProcessSameSelectPendingOnlySync(List> cssps, ref string sql, ReadAnonymousTypeOtherInfo csspsod) + public List> _SameSelectPendingShareData; + internal Select0Provider SetSameSelectPendingShareData(List> data) { - 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; } - 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 - for (var a = 0; a < cssps.Count; a++) - sbSql.Append("\r\nUNION ALL\r\nselect * from (").Append(cssps[a].Item1).Append(") ftb"); + for (var a = 0; a < _SameSelectPendingShareData.Count; a++) + sbSql.Append("\r\nUNION ALL\r\nselect * from (").Append(_SameSelectPendingShareData[a].Item1).Append(") ftb"); 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(); //dbParms = cssps.Select(a => a.Item2).SelectMany(a => a).ToArray(); sbSql.Clear(); } return false; } + internal static Expression SetSameSelectPendingShareDataWithExpression(Expression exp, List> data) + { + var callExp = exp as MethodCallExpression; + var callExpStack = new Stack(); + 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>)) + ); + 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 : Select0Provider, ISelect0 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 }); this.Where(_commonUtils.WhereObject(_tables.First().Table, "a.", dywhere)); if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); - CurrentSameSelectPendingOnlySync?.ForEach(a => _params.AddRange(a?.Item2 ?? new DbParameter[0])); } public TSelect TrackToList(Action track) diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs index 287e995f..9cdbfed4 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0ProviderReader.cs @@ -139,13 +139,12 @@ namespace FreeSql.Internal.CommonProvider } internal List ToListPrivate(GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData) { - var cssps = CurrentSameSelectPendingOnlySync; ReadAnonymousTypeOtherInfo csspsod = null; - if (cssps != null) + if (_SameSelectPendingShareData != null) { var ods = new List(); 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())); + 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())); otherData = ods.ToArray(); } @@ -160,7 +159,7 @@ namespace FreeSql.Internal.CommonProvider else sql = this.ToSql(af.Field); - if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return new List(); + if (SameSelectPending(ref sql, csspsod)) return new List(); return ToListAfPrivate(sql, af, otherData); } #region ToChunk @@ -371,13 +370,12 @@ namespace FreeSql.Internal.CommonProvider } internal List ToListMapReaderPrivate(ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData) { - var cssps = CurrentSameSelectPendingOnlySync; ReadAnonymousTypeOtherInfo csspsod = null; - if (cssps != null) + if (_SameSelectPendingShareData != null) { var ods = new List(); 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())); + 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())); otherData = ods.ToArray(); } @@ -392,7 +390,7 @@ namespace FreeSql.Internal.CommonProvider else sql = this.ToSql(af.field); - if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return new List(); + if (SameSelectPending(ref sql, csspsod)) return new List(); return ToListMrPrivate(sql, af, otherData); } protected List ToListMapReader(ReadAnonymousTypeAfInfo af) => ToListMapReaderPrivate(af, null); @@ -944,11 +942,9 @@ namespace FreeSql.Internal.CommonProvider af.fillSubSelectMany[b].Item2.Add(otherListItem); continue; } - var threadId = Thread.CurrentThread.ManagedThreadId; + var sspShareData = new List>(); try { - _SameSelectPendingOnlySync.TryAdd(threadId, new List>()); - var cssps = CurrentSameSelectPendingOnlySync; var newexp = findSubSelectMany[a]; var newexpParms = otherAfmanys[a].Select(d => { @@ -956,35 +952,35 @@ namespace FreeSql.Internal.CommonProvider newexp = rmev.Replace(newexp, d.Item1, newexpParm); return newexpParm; }).ToArray(); + newexp = SetSameSelectPendingShareDataWithExpression(newexp, sspShareData); var newexpFunc = Expression.Lambda(newexp, newexpParms).Compile(); 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++) { 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); if (c < ret.Count - 1) continue; var otherList = diret as IEnumerable; var retlistidx = 0; foreach (var otherListItem in otherList) { - var retlist = cssps[0].Item3.retlist; + var retlist = sspShareData[0].Item3.retlist; while (retlistidx >= retlist.Count) { - cssps.RemoveAt(0); - retlist = cssps[0].Item3.retlist; + sspShareData.RemoveAt(0); + retlist = sspShareData[0].Item3.retlist; retlistidx = 0; } int.TryParse(retlist[retlistidx++]?.ToString(), out var tryrowidx); af.fillSubSelectMany[tryrowidx * otherAfmanys.Count + a].Item2.Add(otherListItem); } } - cssps.Clear(); } finally { - _SameSelectPendingOnlySync.TryRemove(threadId, out var oldssps); + sspShareData.Clear(); } } return ret; @@ -1225,13 +1221,12 @@ namespace FreeSql.Internal.CommonProvider internal Task> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken) { - var cssps = CurrentSameSelectPendingOnlySync; ReadAnonymousTypeOtherInfo csspsod = null; - if (cssps != null) + if (_SameSelectPendingShareData != null) { var ods = new List(); 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())); + 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())); otherData = ods.ToArray(); } @@ -1246,7 +1241,7 @@ namespace FreeSql.Internal.CommonProvider else sql = this.ToSql(af.Field); - if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return Task.FromResult(new List()); + if (SameSelectPending(ref sql, csspsod)) return Task.FromResult(new List()); return ToListAfPrivateAsync(sql, af, otherData, cancellationToken); } @@ -1327,13 +1322,12 @@ namespace FreeSql.Internal.CommonProvider } internal Task> ToListMapReaderPrivateAsync(ReadAnonymousTypeAfInfo af, ReadAnonymousTypeOtherInfo[] otherData, CancellationToken cancellationToken) { - var cssps = CurrentSameSelectPendingOnlySync; ReadAnonymousTypeOtherInfo csspsod = null; - if (cssps != null) + if (_SameSelectPendingShareData != null) { var ods = new List(); 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())); + 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())); otherData = ods.ToArray(); } @@ -1348,7 +1342,7 @@ namespace FreeSql.Internal.CommonProvider else sql = this.ToSql(af.field); - if (ProcessSameSelectPendingOnlySync(cssps, ref sql, csspsod)) return Task.FromResult(new List()); + if (SameSelectPending(ref sql, csspsod)) return Task.FromResult(new List()); return ToListMrPrivateAsync(sql, af, otherData, cancellationToken); } protected Task> ToListMapReaderAsync(ReadAnonymousTypeAfInfo af, CancellationToken cancellationToken) => ToListMapReaderPrivateAsync(af, null, cancellationToken); @@ -1412,11 +1406,9 @@ namespace FreeSql.Internal.CommonProvider af.fillSubSelectMany[b].Item2.Add(otherListItem); continue; } - var threadId = Thread.CurrentThread.ManagedThreadId; //一定要【注意】 await 会影响该值,以下以容将 ToList 替换成 ToListAsync 后再执行 + var sspShareData = new List>(); try { - _SameSelectPendingOnlySync.TryAdd(threadId, new List>()); - var cssps = CurrentSameSelectPendingOnlySync; var newexp = findSubSelectMany[a]; var newexpParms = otherAfmanys[a].Select(d => { @@ -1450,13 +1442,14 @@ namespace FreeSql.Internal.CommonProvider if (asyncMethod != null) 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 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++) { 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; if (c < ret.Count - 1) continue; @@ -1466,22 +1459,21 @@ namespace FreeSql.Internal.CommonProvider var retlistidx = 0; foreach (var otherListItem in otherList) { - var retlist = cssps[0].Item3.retlist; + var retlist = sspShareData[0].Item3.retlist; while (retlistidx >= retlist.Count) { - cssps.RemoveAt(0); - retlist = cssps[0].Item3.retlist; + sspShareData.RemoveAt(0); + retlist = sspShareData[0].Item3.retlist; retlistidx = 0; } int.TryParse(retlist[retlistidx++]?.ToString(), out var tryrowidx); af.fillSubSelectMany[tryrowidx * otherAfmanys.Count + a].Item2.Add(otherListItem); } } - cssps.Clear(); } finally { - _SameSelectPendingOnlySync.TryRemove(threadId, out var oldssps); + sspShareData.Clear(); } } return ret;