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