From 8c770a3ffb74d31fd9225dc08f1854947ef06b5a Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Tue, 3 Dec 2019 21:16:40 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20IncludeMany=20?= =?UTF-8?q?=E7=BA=A7=E8=81=94=E6=9F=A5=E8=AF=A2=E6=94=AF=E6=8C=81=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E9=80=82=E9=85=8D=EF=BC=88=E4=B9=8B=E5=89=8D=E6=98=AF?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=96=B9=E5=BC=8F=EF=BC=89=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 6 +- .../BaseEntityReadOnly.cs | 2 +- FreeSql.DbContext/FreeSql.DbContext.xml | 7 + .../Sqlite/Curd/SqliteSelectTest.cs | 165 ++++++++++ FreeSql.Tests/FreeSql.Tests/g.cs | 27 +- FreeSql/Extensions/FreeSqlGlobalExtensions.cs | 11 + FreeSql/FreeSql.xml | 287 ++++++++---------- .../SelectProvider/Select0Provider.cs | 16 +- .../SelectProvider/Select1Provider.cs | 79 ++++- 9 files changed, 416 insertions(+), 184 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 949cbac3..798ea5c3 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -4,7 +4,9 @@ using FreeSql.Extensions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; +using System.Diagnostics; using System.Linq.Expressions; +using System.Threading; using System.Threading.Tasks; namespace base_entity @@ -124,8 +126,8 @@ namespace base_entity ru1.RoleId = r2.Id; await ru1.SaveAsync(); - var u1roles = User1.Select.IncludeMany(a => a.Roles).ToList(); - var u1roles2 = User1.Select.Where(a => a.Roles.AsSelect().Any(b => b.Id == "xx")).ToList(); + var u1roles = await User1.Select.IncludeMany(a => a.Roles).ToListAsync(); + var u1roles2 = await User1.Select.Where(a => a.Roles.AsSelect().Any(b => b.Id == "xx")).ToListAsync(); }).Wait(); diff --git a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs index e7e82ce5..60ce244a 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs +++ b/Extensions/FreeSql.Extensions.BaseEntity/BaseEntityReadOnly.cs @@ -36,7 +36,7 @@ namespace FreeSql public static void Initialization(IFreeSql fsql) { _ormPriv = fsql; - _ormPriv.Aop.CurdBefore += (s, e) => Trace.WriteLine(e.Sql + "\r\n"); + _ormPriv.Aop.CurdBefore += (s, e) => Trace.WriteLine($"\r\n线程{Thread.CurrentThread.ManagedThreadId}: {e.Sql}\r\n"); } /// diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index dc0203b8..d9f91124 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -110,6 +110,13 @@ 清空状态数据 + + + 根据 lambda 条件删除数据 + + + + 添加 diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index d2e262ca..75739c13 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -2,6 +2,8 @@ using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Xunit; namespace FreeSql.Tests.Sqlite @@ -1375,6 +1377,169 @@ namespace FreeSql.Tests.Sqlite .ToList(true); } + [Fact] + async public Task Include_ManyToManyAsync() + { + ThreadPool.SetMinThreads(100, 100); + await Task.Yield(); + + var tag1 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_manytoMany_01_中国" + }; + tag1.Id = (int)await g.sqlite.Insert(tag1).ExecuteIdentityAsync(); + var tag2 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_manytoMany_02_美国" + }; + tag2.Id = (int)await g.sqlite.Insert(tag2).ExecuteIdentityAsync(); + var tag3 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_manytoMany_03_日本" + }; + tag3.Id = (int)await g.sqlite.Insert(tag3).ExecuteIdentityAsync(); + + var song1 = new Song + { + Create_time = DateTime.Now, + Title = "test_manytoMany_01_我是中国人.mp3", + Url = "http://ww.baidu.com/" + }; + song1.Id = (int)await g.sqlite.Insert(song1).ExecuteIdentityAsync(); + var song2 = new Song + { + Create_time = DateTime.Now, + Title = "test_manytoMany_02_爱你一万年.mp3", + Url = "http://ww.163.com/" + }; + song2.Id = (int)await g.sqlite.Insert(song2).ExecuteIdentityAsync(); + var song3 = new Song + { + Create_time = DateTime.Now, + Title = "test_manytoMany_03_千年等一回.mp3", + Url = "http://ww.sina.com/" + }; + song3.Id = (int)await g.sqlite.Insert(song3).ExecuteIdentityAsync(); + + await g.sqlite.Insert(new Song_tag { Song_id = song1.Id, Tag_id = tag1.Id }).ExecuteAffrowsAsync(); + await g.sqlite.Insert(new Song_tag { Song_id = song2.Id, Tag_id = tag1.Id }).ExecuteAffrowsAsync(); + await g.sqlite.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag1.Id }).ExecuteAffrowsAsync(); + await g.sqlite.Insert(new Song_tag { Song_id = song1.Id, Tag_id = tag2.Id }).ExecuteAffrowsAsync(); + await g.sqlite.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag2.Id }).ExecuteAffrowsAsync(); + await g.sqlite.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag3.Id }).ExecuteAffrowsAsync(); + + await new List(new[] { song1, song2, song3 }).IncludeManyAsync(g.sqlite, a => a.Tags); + + var songs1 = await g.sqlite.Select() + .IncludeMany(a => a.Tags) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs1.Count); + Assert.Equal(2, songs1[0].Tags.Count); + Assert.Equal(1, songs1[1].Tags.Count); + Assert.Equal(3, songs1[2].Tags.Count); + + var songs2 = await g.sqlite.Select() + .IncludeMany(a => a.Tags, + then => then.IncludeMany(t => t.Songs)) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs2.Count); + Assert.Equal(2, songs2[0].Tags.Count); + Assert.Equal(1, songs2[1].Tags.Count); + Assert.Equal(3, songs2[2].Tags.Count); + + var tags3 = await g.sqlite.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToListAsync(true); + + + var songs11 = await g.sqlite.Select() + .IncludeMany(a => a.Tags.Take(1)) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs11.Count); + Assert.Equal(1, songs11[0].Tags.Count); + Assert.Equal(1, songs11[1].Tags.Count); + Assert.Equal(1, songs11[2].Tags.Count); + + var songs22 = await g.sqlite.Select() + .IncludeMany(a => a.Tags.Take(1), + then => then.IncludeMany(t => t.Songs.Take(1))) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs22.Count); + Assert.Equal(1, songs22[0].Tags.Count); + Assert.Equal(1, songs22[1].Tags.Count); + Assert.Equal(1, songs22[2].Tags.Count); + + var tags33 = await g.sqlite.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs.Take(1)) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToListAsync(true); + + // --- Select --- + + await new List(new[] { song1, song2, song3 }).IncludeManyAsync(g.sqlite, a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name })); + + var asongs1 = await g.sqlite.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name })) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs1.Count); + Assert.Equal(2, songs1[0].Tags.Count); + Assert.Equal(1, songs1[1].Tags.Count); + Assert.Equal(3, songs1[2].Tags.Count); + + var asongs2 = await g.sqlite.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.IncludeMany(t => t.Songs.Select(b => new Song { Id = b.Id, Title = b.Title }))) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs2.Count); + Assert.Equal(2, songs2[0].Tags.Count); + Assert.Equal(1, songs2[1].Tags.Count); + Assert.Equal(3, songs2[2].Tags.Count); + + var atags3 = await g.sqlite.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToListAsync(true); + + + var asongs11 = await g.sqlite.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name })) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs11.Count); + Assert.Equal(1, songs11[0].Tags.Count); + Assert.Equal(1, songs11[1].Tags.Count); + Assert.Equal(1, songs11[2].Tags.Count); + + var asongs22 = await g.sqlite.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.IncludeMany(t => t.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title }))) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToListAsync(); + Assert.Equal(3, songs22.Count); + Assert.Equal(1, songs22[0].Tags.Count); + Assert.Equal(1, songs22[1].Tags.Count); + Assert.Equal(1, songs22[2].Tags.Count); + + var atags33 = await g.sqlite.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToListAsync(true); + } + public class ToDel1Pk { [Column(IsIdentity = true)] diff --git a/FreeSql.Tests/FreeSql.Tests/g.cs b/FreeSql.Tests/FreeSql.Tests/g.cs index 4c336e30..0c8aac09 100644 --- a/FreeSql.Tests/FreeSql.Tests/g.cs +++ b/FreeSql.Tests/FreeSql.Tests/g.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; - +using System.Threading; public class g { @@ -13,8 +13,9 @@ public class g .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseMonitorCommand( - cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 - (cmd, traceLog) => Console.WriteLine(traceLog)) + cmd => Trace.WriteLine("\r\n线程" + Thread.CurrentThread.ManagedThreadId + ": " + cmd.CommandText) //监听SQL命令对象,在执行前 + //, (cmd, traceLog) => Console.WriteLine(traceLog) + ) .UseLazyLoading(true) .Build()); public static IFreeSql mysql => mysqlLazy.Value; @@ -29,8 +30,9 @@ public class g .UseSyncStructureToLower(true) .UseLazyLoading(true) .UseMonitorCommand( - cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 - (cmd, traceLog) => Console.WriteLine(traceLog)) + cmd => Trace.WriteLine("\r\n线程" + Thread.CurrentThread.ManagedThreadId + ": " + cmd.CommandText) //监听SQL命令对象,在执行前 + //, (cmd, traceLog) => Console.WriteLine(traceLog) + ) .Build(); }); public static IFreeSql pgsql => pgsqlLazy.Value; @@ -41,8 +43,9 @@ public class g .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseMonitorCommand( - cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 - (cmd, traceLog) => Console.WriteLine(traceLog)) + cmd => Trace.WriteLine("\r\n线程" + Thread.CurrentThread.ManagedThreadId + ": " + cmd.CommandText) //监听SQL命令对象,在执行前 + //, (cmd, traceLog) => Console.WriteLine(traceLog) + ) .UseLazyLoading(true) .Build()); public static IFreeSql sqlserver => sqlserverLazy.Value; @@ -56,8 +59,9 @@ public class g //.UseNoneCommandParameter(true) .UseMonitorCommand( - cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 - (cmd, traceLog) => Console.WriteLine(traceLog)) + cmd => Trace.WriteLine("\r\n线程" + Thread.CurrentThread.ManagedThreadId + ": " + cmd.CommandText) //监听SQL命令对象,在执行前 + //, (cmd, traceLog) => Console.WriteLine(traceLog) + ) .Build()); public static IFreeSql oracle => oracleLazy.Value; @@ -67,8 +71,9 @@ public class g //.UseGenerateCommandParameterWithLambda(true) .UseLazyLoading(true) .UseMonitorCommand( - cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 - (cmd, traceLog) => Console.WriteLine(traceLog)) + cmd => Trace.WriteLine("\r\n线程" + Thread.CurrentThread.ManagedThreadId + ": " + cmd.CommandText) //监听SQL命令对象,在执行前 + //, (cmd, traceLog) => Console.WriteLine(traceLog) + ) .Build()); public static IFreeSql sqlite => sqliteLazy.Value; } diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index e94e9eb8..29b0c08f 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -210,5 +210,16 @@ public static partial class FreeSqlGlobalExtensions select.SetList(list); return list; } + +#if net40 +#else + async public static System.Threading.Tasks.Task> IncludeManyAsync(this List list, IFreeSql orm, Expression>> navigateSelector, Action> then = null) where T1 : class where TNavigate : class + { + if (list == null || list.Any() == false) return list; + var select = orm.Select().IncludeMany(navigateSelector, then) as FreeSql.Internal.CommonProvider.Select1Provider; + await select.SetListAsync(list); + return list; + } +#endif #endregion } \ No newline at end of file diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 5151df8a..768d92dd 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -2049,6 +2049,137 @@ + + + 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 + + + + + + + + + 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 }) + + + + + + + 查询 + + + + + + + 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 }) + + + + + + + + 查询 + + + + + + + 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 }) + + + + + + + + 查询 + + + + + + + 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 }) + + + + + + + + 在【主库】执行 + + + + + + + + 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 }) + + + + + + + + 在【主库】执行 + + + + + + + + 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 }) + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 }) + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new { age = 25 }) + + + + + + 可自定义解析表达式 @@ -2764,159 +2895,3 @@ - - - - 使用 or 拼接两个 lambda 表达式 - - - - - - 使用 or 拼接两个 lambda 表达式 - - - - true 时生效 - - - - - - 将 lambda 表达式取反 - - - - true 时生效 - - - - - 生成类似Mongodb的ObjectId有序、不重复Guid - - - - - - 插入数据 - - - - - - - 插入数据,传入实体 - - - - - - - - 插入数据,传入实体数组 - - - - - - - - 插入数据,传入实体集合 - - - - - - - - 插入数据,传入实体集合 - - - - - - - - 修改数据 - - - - - - - 修改数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 查询数据 - - - - - - - 查询数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 删除数据 - - - - - - - 删除数据,传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 开启事务(不支持异步),60秒未执行完将自动提交 - - 事务体 () => {} - - - - 开启事务(不支持异步) - - 事务体 () => {} - 超时,未执行完将自动提交 - - - - 数据库访问对象 - - - - - 所有拦截方法都在这里 - - - - - CodeFirst 模式开发相关方法 - - - - - DbFirst 模式开发相关方法 - - - - - 全局过滤设置,可默认附加为 Select/Update/Delete 条件 - - - - diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 41ae2e15..0c7aa3c2 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -34,6 +34,10 @@ namespace FreeSql.Internal.CommonProvider protected DbConnection _connection; protected Action _trackToList; protected List> _includeToList = new List>(); +#if net40 +#else + protected List> _includeToListAsync = new List>(); +#endif protected bool _distinct; protected Expression _selectExpression; protected List _whereCascadeExpression = new List(); @@ -50,6 +54,10 @@ namespace FreeSql.Internal.CommonProvider _join.Clear(); _trackToList = null; _includeToList.Clear(); +#if net40 +#else + _includeToListAsync.Clear(); +#endif _selectExpression = null; _whereCascadeExpression.Clear(); _whereGlobalFilter = _orm.GlobalFilter.GetFilters(); @@ -104,6 +112,10 @@ namespace FreeSql.Internal.CommonProvider toType.GetField("_connection", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._connection); toType.GetField("_trackToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._trackToList); toType.GetField("_includeToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._includeToList); +#if net40 +#else + toType.GetField("_includeToListAsync", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._includeToListAsync); +#endif toType.GetField("_distinct", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._distinct); toType.GetField("_selectExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._selectExpression); toType.GetField("_whereCascadeExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._whereCascadeExpression); @@ -1154,7 +1166,7 @@ namespace FreeSql.Internal.CommonProvider var after = new Aop.CurdAfterEventArgs(before, exception, ret); _orm.Aop.CurdAfter?.Invoke(this, after); } - foreach (var include in _includeToList) include?.Invoke(ret); + foreach (var include in _includeToListAsync) await include?.Invoke(ret); _trackToList?.Invoke(ret); return ret; } @@ -1220,7 +1232,7 @@ namespace FreeSql.Internal.CommonProvider _orm.Aop.CurdAfter?.Invoke(this, after); } if (typeof(TReturn) == typeof(T1)) - foreach (var include in _includeToList) include?.Invoke(ret); + foreach (var include in _includeToListAsync) await include?.Invoke(ret); _trackToList?.Invoke(ret); return ret; } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index c84f2328..1f65260f 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -533,9 +533,16 @@ namespace FreeSql.Internal.CommonProvider } if (tbref.Columns.Any() == false) throw throwNavigateSelector; } - - _includeToList.Add(listObj => + +#if net40 + Action includeToListSyncOrAsync = (listObj, isAsync) => { + isAsync = false; +#else + Func includeToListSyncOrAsync = async (listObj, isAsync) => + { +#endif + var list = listObj as List; if (list == null) return; if (list.Any() == false) return; @@ -576,7 +583,7 @@ namespace FreeSql.Internal.CommonProvider Expression.Block( Expression.Return(returnTarget, Expression.Call(null, GetEntityValueWithPropertyNameMethod, Expression.Constant(_orm), Expression.Constant(membersExp.Type), membersExp, propertyNameExp)), Expression.Label(returnTarget, Expression.Default(typeof(object))) - ), t1parm, propertyNameExp).Compile(): + ), t1parm, propertyNameExp).Compile() : Expression.Lambda>( Expression.Block( Expression.IfThen( @@ -700,8 +707,20 @@ namespace FreeSql.Internal.CommonProvider sbSql.Remove(0, 13); if (sbDic.Count == 1) sbSql.Remove(0, 15).Remove(sbSql.Length - 5, 5); sbDic.Clear(); - if (selectExp == null) subList = subSelect.ToListAfPrivate(sbSql.ToString(), af, null); - else subList = subSelect.ToListMrPrivate(sbSql.ToString(), mf, null); + + if (isAsync) + { +#if net40 +#else + if (selectExp == null) subList = await subSelect.ToListAfPrivateAsync(sbSql.ToString(), af, null); + else subList = await subSelect.ToListMrPrivateAsync(sbSql.ToString(), mf, null); +#endif + } + else + { + if (selectExp == null) subList = subSelect.ToListAfPrivate(sbSql.ToString(), af, null); + else subList = subSelect.ToListMrPrivate(sbSql.ToString(), mf, null); + } sbSql.Clear(); } else @@ -731,8 +750,20 @@ namespace FreeSql.Internal.CommonProvider sbDic.Clear(); } subSelect.Where(oldWhere); - if (selectExp == null) subList = subSelect.ToList(true); - else subList = subSelect.ToList(selectExp); + + if (isAsync) + { +#if net40 +#else + if (selectExp == null) subList = await subSelect.ToListAsync(true); + else subList = await subSelect.ToListAsync(selectExp); +#endif + } + else + { + if (selectExp == null) subList = subSelect.ToList(true); + else subList = subSelect.ToList(selectExp); + } } if (subList.Any() == false) @@ -826,7 +857,8 @@ namespace FreeSql.Internal.CommonProvider { if (z > 0) sbJoin.Append(" AND "); sbJoin.Append($"midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[tbref.Columns.Count + z].Attribute.Name)} = a.{_commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)}"); - if (_whereCascadeExpression.Any()) { + if (_whereCascadeExpression.Any()) + { var cascade = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Alias = "midtb", AliasInit = "midtb", Table = tbrefMid, Type = SelectTableInfoType.InnerJoin }, _whereCascadeExpression); if (string.IsNullOrEmpty(cascade) == false) sbJoin.Append(" AND (").Append(cascade).Append(")"); @@ -843,7 +875,7 @@ namespace FreeSql.Internal.CommonProvider var sbSql = new StringBuilder(); if (_selectExpression == null) - {// return this.InternalToList(_selectExpression).Select(a => (a, ()).ToList(); + { var field = new StringBuilder(); var read = new ReadAnonymousTypeInfo(); read.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; @@ -919,8 +951,19 @@ namespace FreeSql.Internal.CommonProvider sbSql.Append(subSelect.ToSql($"{(selectExp == null ? af.Field : mf.field)}{otherData?.field}")); } - if (selectExp == null) subList = subSelect.ToListAfPrivate(sbSql.ToString(), af, otherData == null ? null : new[] { (otherData.Value.field, otherData.Value.read, midList) }); - else subList = subSelect.ToListMrPrivate(sbSql.ToString(), mf, otherData == null ? null : new[] { (otherData.Value.field, otherData.Value.read, midList) }); + if (isAsync) + { +#if net40 +#else + if (selectExp == null) subList = await subSelect.ToListAfPrivateAsync(sbSql.ToString(), af, otherData == null ? null : new[] { (otherData.Value.field, otherData.Value.read, midList) }); + else subList = await subSelect.ToListMrPrivateAsync(sbSql.ToString(), mf, otherData == null ? null : new[] { (otherData.Value.field, otherData.Value.read, midList) }); +#endif + } + else + { + if (selectExp == null) subList = subSelect.ToListAfPrivate(sbSql.ToString(), af, otherData == null ? null : new[] { (otherData.Value.field, otherData.Value.read, midList) }); + else subList = subSelect.ToListMrPrivate(sbSql.ToString(), mf, otherData == null ? null : new[] { (otherData.Value.field, otherData.Value.read, midList) }); + } if (subList.Any() == false) { foreach (var item in list) @@ -983,7 +1026,13 @@ namespace FreeSql.Internal.CommonProvider } break; } - }); + }; + + _includeToList.Add(listObj => includeToListSyncOrAsync(listObj, false)); +#if net40 +#else + _includeToListAsync.Add(listObj => includeToListSyncOrAsync(listObj, true)); +#endif return this; } @@ -995,6 +1044,12 @@ namespace FreeSql.Internal.CommonProvider #if net40 #else + async internal Task SetListAsync(IEnumerable list) + { + foreach (var include in _includeToListAsync) await include?.Invoke(list); + _trackToList?.Invoke(list); + } + public Task AvgAsync(Expression> column) { if (column == null) return Task.FromResult(default(TMember));