From e1e3e4a3b27f021e4d368573ef9bcdd6cc469f2a Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Tue, 17 Dec 2019 01:39:53 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20Where=20In=20=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90=EF=BC=9B=20-=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20FreeSqlBuilder.UseConnectionFactory=20=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E7=9A=84=E5=88=9B=E5=BB=BA=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FreeSql.Tests.PerformanceTests.csproj | 2 +- .../MySqlConnector/Curd/MySqlSelectTest.cs | 42 +- .../g.cs | 2 + .../Dameng/Curd/DamengSelectTest.cs | 42 +- .../Default/Curd/OdbcSelectTest.cs | 46 +- .../MySql/Curd/MySqlSelectTest.cs | 42 +- .../Oracle/Curd/OracleSelectTest.cs | 42 +- .../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 42 +- .../SqlServer/Curd/SqlServerSelectTest.cs | 46 +- .../FreeSql.Tests.Provider.Odbc/g.cs | 7 + .../MySql/Curd/MySqlSelectTest.cs | 44 +- .../Oracle/Curd/OracleSelectTest.cs | 42 +- .../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 42 +- .../SqlServer/Curd/SqlServerSelectTest.cs | 38 +- .../Sqlite/Curd/SqliteSelectTest.cs | 42 +- FreeSql.Tests/FreeSql.Tests/g.cs | 15 + FreeSql.sln | 2 +- FreeSql/FreeSql.csproj | 2 +- FreeSql/FreeSql.xml | 487 +++++++----------- FreeSql/FreeSqlBuilder.cs | 25 +- FreeSql/Interface/IAdo.cs | 4 +- FreeSql/Internal/CommonExpression.cs | 5 +- .../CommonProvider/AdoProvider/AdoProvider.cs | 20 +- .../AdoProvider/AdoProviderAsync.cs | 6 +- .../AdoProvider/AdoProviderTransaction.cs | 2 +- .../AdoProvider/DbConnectionPool.cs | 134 +++++ .../MySqlAdo/MySqlAdo.cs | 13 +- .../FreeSql.Provider.MySql/MySqlProvider.cs | 4 +- .../Dameng/OdbcDamengAdo/OdbcDamengAdo.cs | 15 +- .../OdbcDamengAdo/OdbcDamengConnectionPool.cs | 11 +- .../Dameng/OdbcDamengCodeFirst.cs | 7 +- .../Dameng/OdbcDamengProvider.cs | 4 +- .../Default/OdbcAdo/OdbcAdo.cs | 13 +- .../Default/OdbcProvider.cs | 5 +- .../GBase/OdbcGBaseAdo/__OdbcGBaseAdo.cs | 13 +- .../GBase/OdbcGBaseProvider.cs | 5 +- .../MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs | 15 +- .../MySql/OdbcMySqlProvider.cs | 4 +- .../Oracle/OdbcOracleAdo/OdbcOracleAdo.cs | 15 +- .../OdbcOracleAdo/OdbcOracleConnectionPool.cs | 11 +- .../Oracle/OdbcOracleCodeFirst.cs | 7 +- .../Oracle/OdbcOracleProvider.cs | 4 +- .../OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs | 15 +- .../PostgreSQL/OdbcPostgreSQLProvider.cs | 5 +- .../OdbcSqlServerAdo/OdbcSqlServerAdo.cs | 15 +- .../SqlServer/OdbcSqlServerProvider.cs | 5 +- .../OracleAdo/OracleAdo.cs | 13 +- .../OracleAdo/OracleConnectionPool.cs | 11 +- .../OracleCodeFirst.cs | 7 +- .../FreeSql.Provider.Oracle/OracleProvider.cs | 4 +- .../PostgreSQLAdo/PostgreSQLAdo.cs | 15 +- .../PostgreSQLProvider.cs | 4 +- .../SqlServerAdo/SqlServerAdo.cs | 13 +- .../SqlServerProvider.cs | 5 +- .../SqliteAdo/SqliteAdo.cs | 13 +- .../SqliteAdo/SqliteConnectionPool.cs | 12 +- .../FreeSql.Provider.Sqlite/SqliteProvider.cs | 4 +- 57 files changed, 1018 insertions(+), 492 deletions(-) create mode 100644 FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs diff --git a/FreeSql.Tests/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj b/FreeSql.Tests/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj index 896199f9..c86a28d6 100644 --- a/FreeSql.Tests/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj +++ b/FreeSql.Tests/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj @@ -19,7 +19,7 @@ - + diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs index cf5f41f3..571ff538 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs @@ -832,12 +832,16 @@ namespace FreeSql.Tests.MySqlConnector var subquery = select.ToSql(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT sum(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -846,12 +850,16 @@ namespace FreeSql.Tests.MySqlConnector var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT min(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -860,12 +868,16 @@ namespace FreeSql.Tests.MySqlConnector var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT max(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -874,15 +886,29 @@ namespace FreeSql.Tests.MySqlConnector var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT avg(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` +FROM `tb_topic` a +WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` + FROM `tb_topic` b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs index a5942054..bd67be80 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs @@ -9,11 +9,13 @@ public class g static Lazy mysqlLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10") + //.UseConnectionFactory(FreeSql.DataType.MySql, () => new MySql.Data.MySqlClient.MySqlConnection("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;")) .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseMonitorCommand( cmd => { + cmd.CommandTimeout = 200000; Trace.WriteLine(cmd.CommandText); }, //监听SQL命令对象,在执行前 (cmd, traceLog) => diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs index 5e8e8135..0f2ff099 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs @@ -758,12 +758,16 @@ namespace FreeSql.Tests.Odbc.Dameng var subquery = select.ToSql(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT sum(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -772,12 +776,16 @@ namespace FreeSql.Tests.Odbc.Dameng var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT min(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -786,12 +794,16 @@ namespace FreeSql.Tests.Odbc.Dameng var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT max(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -800,15 +812,29 @@ namespace FreeSql.Tests.Odbc.Dameng var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT avg(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""ID"", a.""CLICKS"", a.""TYPEGUID"", a.""TITLE"", a.""CREATETIME"" +FROM ""TB_TOPIC22"" a +WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" + FROM ""TB_TOPIC22"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs index 63a22cb8..4bbf76e3 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs @@ -725,15 +725,18 @@ namespace FreeSql.Tests.Odbc.Default [Fact] public void Sum() { - var subquery = select.Where(a => a.Id < 200).ToSql(a => new + var subquery = select.ToSql(a => new { all = a, - count = select.Where(b => b.Id < 200).Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); - var subqueryList = select.Where(a => a.Id < 200).ToList(a => new + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 sum(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); + var subqueryList = select.ToList(a => new { all = a, - count = select.Where(b => b.Id < 200).Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -742,12 +745,15 @@ namespace FreeSql.Tests.Odbc.Default var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 min(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -756,29 +762,45 @@ namespace FreeSql.Tests.Odbc.Default var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 max(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] public void Avg() { - var subquery = select.Where(a => a.Id < 200).ToSql(a => new + var subquery = select.ToSql(a => new { all = a, - count = select.Where(b => b.Id < 200).Sum(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); - var subqueryList = select.Where(a => a.Id < 200).ToList(a => new + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 avg(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); + var subqueryList = select.ToList(a => new { all = a, - count = select.Where(b => b.Id < 200).Sum(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a.[Title], a.[CreateTime] +FROM [tb_topic22] a +WHERE (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title] + FROM [tb_topic22] b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs index 75597ce2..c6b9f900 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs @@ -843,12 +843,16 @@ namespace FreeSql.Tests.Odbc.MySql var subquery = select.ToSql(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT sum(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -857,12 +861,16 @@ namespace FreeSql.Tests.Odbc.MySql var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT min(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -871,12 +879,16 @@ namespace FreeSql.Tests.Odbc.MySql var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT max(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -885,15 +897,29 @@ namespace FreeSql.Tests.Odbc.MySql var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT avg(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` +FROM `tb_topic` a +WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` + FROM `tb_topic` b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs index 363a1548..6f0bfc79 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs @@ -758,12 +758,16 @@ namespace FreeSql.Tests.Odbc.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT sum(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -772,12 +776,16 @@ namespace FreeSql.Tests.Odbc.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT min(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -786,12 +794,16 @@ namespace FreeSql.Tests.Odbc.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT max(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -800,15 +812,29 @@ namespace FreeSql.Tests.Odbc.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT avg(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""ID"", a.""CLICKS"", a.""TYPEGUID"", a.""TITLE"", a.""CREATETIME"" +FROM ""TB_TOPIC22"" a +WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" + FROM ""TB_TOPIC22"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 4599275e..eae61153 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -815,12 +815,16 @@ namespace FreeSql.Tests.Odbc.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT sum(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -829,12 +833,16 @@ namespace FreeSql.Tests.Odbc.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT min(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -843,12 +851,16 @@ namespace FreeSql.Tests.Odbc.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT max(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -857,15 +869,29 @@ namespace FreeSql.Tests.Odbc.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT avg(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""id"", a.""clicks"", a.""typeguid"", a.""title"", a.""createtime"" +FROM ""tb_topic"" a +WHERE ((((a.""id"")::varchar) in (SELECT b.""title"" + FROM ""tb_topic"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs index e750c5c4..9e7c6e74 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs @@ -706,15 +706,18 @@ namespace FreeSql.Tests.Odbc.SqlServer [Fact] public void Sum() { - var subquery = select.Where(a => a.Id < 200).ToSql(a => new + var subquery = select.ToSql(a => new { all = a, - count = select.Where(b => b.Id < 200).Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); - var subqueryList = select.Where(a => a.Id < 200).ToList(a => new + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 sum(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); + var subqueryList = select.ToList(a => new { all = a, - count = select.Where(b => b.Id < 200).Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -723,12 +726,15 @@ namespace FreeSql.Tests.Odbc.SqlServer var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 min(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -737,29 +743,45 @@ namespace FreeSql.Tests.Odbc.SqlServer var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 max(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] public void Avg() { - var subquery = select.Where(a => a.Id < 100).ToSql(a => new + var subquery = select.ToSql(a => new { all = a, - count = select.Where(b => b.Id < 100).Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); - var subqueryList = select.Where(a => a.Id < 100).ToList(a => new + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 avg(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); + var subqueryList = select.ToList(a => new { all = a, - count = select.Where(b => b.Id < 100).Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a.[Title], a.[CreateTime] +FROM [tb_topic22] a +WHERE (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title] + FROM [tb_topic22] b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/g.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/g.cs index b00b6d96..1de7386f 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/g.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/g.cs @@ -8,6 +8,7 @@ public class g { static Lazy mysqlLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.OdbcMySql, "Driver={MySQL ODBC 8.0 Unicode Driver};Server=127.0.0.1;Persist Security Info=False;Trusted_Connection=Yes;UID=root;PWD=root;DATABASE=cccddd_odbc;Charset=utf8;SslMode=none;Max pool size=2") + //.UseConnectionFactory(FreeSql.DataType.OdbcMySql, () => new System.Data.Odbc.OdbcConnection("Driver={MySQL ODBC 8.0 Unicode Driver};Server=127.0.0.1;Persist Security Info=False;Trusted_Connection=Yes;UID=root;PWD=root;DATABASE=cccddd_odbc;Charset=utf8;SslMode=none;")) .UseAutoSyncStructure(true) .UseMonitorCommand( cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 @@ -18,7 +19,9 @@ public class g static Lazy sqlserverLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.OdbcSqlServer, "Driver={SQL Server};Server=.;Persist Security Info=False;Trusted_Connection=Yes;Integrated Security=True;DATABASE=freesqlTest_odbc;Pooling=true;Max pool size=3") + //.UseConnectionFactory(FreeSql.DataType.OdbcSqlServer, () => new System.Data.Odbc.OdbcConnection("Driver={SQL Server};Server=.;Persist Security Info=False;Trusted_Connection=Yes;Integrated Security=True;DATABASE=freesqlTest_odbc;Pooling=true;")) //.UseConnectionString(FreeSql.DataType.OdbcSqlServer, "Driver={SQL Server};Server=192.168.164.129;Persist Security Info=False;Trusted_Connection=Yes;UID=sa;PWD=123456;DATABASE=ds_shop;") + //.UseConnectionFactory(FreeSql.DataType.OdbcSqlServer, () => new System.Data.Odbc.OdbcConnection("Driver={SQL Server};Server=192.168.164.129;Persist Security Info=False;Trusted_Connection=Yes;UID=sa;PWD=123456;DATABASE=ds_shop;")) .UseAutoSyncStructure(true) .UseMonitorCommand( cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 @@ -29,6 +32,7 @@ public class g static Lazy oracleLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.OdbcOracle, "Driver={Oracle in XE};Server=//127.0.0.1:1521/XE;Persist Security Info=False;Trusted_Connection=Yes;UID=odbc1;PWD=123456") + //.UseConnectionFactory(FreeSql.DataType.OdbcOracle, () => new System.Data.Odbc.OdbcConnection("Driver={Oracle in XE};Server=//127.0.0.1:1521/XE;Persist Security Info=False;Trusted_Connection=Yes;UID=odbc1;PWD=123456")) .UseAutoSyncStructure(true) .UseLazyLoading(true) .UseSyncStructureToUpper(true) @@ -44,6 +48,7 @@ public class g { return new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.OdbcPostgreSQL, "Driver={PostgreSQL Unicode(x64)};Server=192.168.164.10;Port=5432;UID=postgres;PWD=123456;Database=tedb_odbc;Pooling=true;Maximum Pool Size=2") + //.UseConnectionFactory(FreeSql.DataType.OdbcPostgreSQL, () => new System.Data.Odbc.OdbcConnection("Driver={PostgreSQL Unicode(x64)};Server=192.168.164.10;Port=5432;UID=postgres;PWD=123456;Database=tedb_odbc;Pooling=true;")) .UseAutoSyncStructure(true) .UseSyncStructureToLower(true) .UseLazyLoading(true) @@ -56,6 +61,7 @@ public class g static Lazy odbcLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Odbc, "Driver={SQL Server};Server=.;Persist Security Info=False;Trusted_Connection=Yes;Integrated Security=True;DATABASE=freesqlTest_odbc;Pooling=true;Max pool size=5") + //.UseConnectionFactory(FreeSql.DataType.Odbc, () => new System.Data.Odbc.OdbcConnection("Driver={SQL Server};Server=.;Persist Security Info=False;Trusted_Connection=Yes;Integrated Security=True;DATABASE=freesqlTest_odbc;Pooling=true;")) .UseMonitorCommand( cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 (cmd, traceLog) => Console.WriteLine(traceLog)) @@ -65,6 +71,7 @@ public class g static Lazy damemgLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.OdbcDameng, "Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789") + //.UseConnectionFactory(FreeSql.DataType.OdbcDameng, () => new System.Data.Odbc.OdbcConnection("Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789")) .UseAutoSyncStructure(true) .UseLazyLoading(true) .UseSyncStructureToUpper(true) diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index 61555675..d2a251fc 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -874,12 +874,16 @@ namespace FreeSql.Tests.MySql var subquery = select.ToSql(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT sum(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -888,12 +892,16 @@ namespace FreeSql.Tests.MySql var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT min(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -902,12 +910,16 @@ namespace FreeSql.Tests.MySql var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) - }); + count = select.As("b").Max(b => b.Id) + }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT max(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -916,15 +928,29 @@ namespace FreeSql.Tests.MySql var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5, (SELECT avg(b.`Id`) + FROM `tb_topic` b + limit 0,1) as6 +FROM `tb_topic` a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` +FROM `tb_topic` a +WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` + FROM `tb_topic` b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index 8a194d9d..0e4e657c 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -758,12 +758,16 @@ namespace FreeSql.Tests.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT sum(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -772,12 +776,16 @@ namespace FreeSql.Tests.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT min(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -786,12 +794,16 @@ namespace FreeSql.Tests.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT max(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -800,15 +812,29 @@ namespace FreeSql.Tests.Oracle var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT avg(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""ID"", a.""CLICKS"", a.""TYPEGUID"", a.""TITLE"", a.""CREATETIME"" +FROM ""TB_TOPIC22"" a +WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" + FROM ""TB_TOPIC22"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 20c1f3b8..9418b8d0 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -832,12 +832,16 @@ namespace FreeSql.Tests.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT sum(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = (long)select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -846,12 +850,16 @@ namespace FreeSql.Tests.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT min(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -860,12 +868,16 @@ namespace FreeSql.Tests.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT max(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -874,15 +886,29 @@ namespace FreeSql.Tests.PostgreSQL var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.""id"" as1, a.""clicks"" as2, a.""typeguid"" as3, a.""title"" as4, a.""createtime"" as5, (SELECT avg(b.""id"") + FROM ""tb_topic"" b + limit 1) as6 +FROM ""tb_topic"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""id"", a.""clicks"", a.""typeguid"", a.""title"", a.""createtime"" +FROM ""tb_topic"" a +WHERE ((((a.""id"")::varchar) in (SELECT b.""title"" + FROM ""tb_topic"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index 8e31fc48..fef4aa42 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -754,12 +754,15 @@ namespace FreeSql.Tests.SqlServer var subquery = select.ToSql(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 sum(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -768,12 +771,15 @@ namespace FreeSql.Tests.SqlServer var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 min(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -782,12 +788,15 @@ namespace FreeSql.Tests.SqlServer var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 max(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -796,15 +805,28 @@ namespace FreeSql.Tests.SqlServer var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.[Id] as1, a.[Clicks] as2, a.[TypeGuid] as3, a.[Title] as4, a.[CreateTime] as5, (SELECT TOP 1 avg(b.[Id]) + FROM [tb_topic22] b) as6 +FROM [tb_topic22] a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a.[Title], a.[CreateTime] +FROM [tb_topic22] a +WHERE (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title] + FROM [tb_topic22] b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index ac2c24a6..743bb309 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -711,12 +711,16 @@ namespace FreeSql.Tests.Sqlite var subquery = select.ToSql(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); + Assert.Equal(@"SELECT a.""Id"" as1, a.""Clicks"" as2, a.""TypeGuid"" as3, a.""Title"" as4, a.""CreateTime"" as5, (SELECT sum(b.""Id"") + FROM ""tb_topic22"" b + limit 0,1) as6 +FROM ""tb_topic22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Sum(b => b.Id) + count = (long)select.As("b").Sum(b => b.Id) }); } [Fact] @@ -725,12 +729,16 @@ namespace FreeSql.Tests.Sqlite var subquery = select.ToSql(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); + Assert.Equal(@"SELECT a.""Id"" as1, a.""Clicks"" as2, a.""TypeGuid"" as3, a.""Title"" as4, a.""CreateTime"" as5, (SELECT min(b.""Id"") + FROM ""tb_topic22"" b + limit 0,1) as6 +FROM ""tb_topic22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Min(b => b.Id) + count = select.As("b").Min(b => b.Id) }); } [Fact] @@ -739,12 +747,16 @@ namespace FreeSql.Tests.Sqlite var subquery = select.ToSql(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); + Assert.Equal(@"SELECT a.""Id"" as1, a.""Clicks"" as2, a.""TypeGuid"" as3, a.""Title"" as4, a.""CreateTime"" as5, (SELECT max(b.""Id"") + FROM ""tb_topic22"" b + limit 0,1) as6 +FROM ""tb_topic22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Max(b => b.Id) + count = select.As("b").Max(b => b.Id) }); } [Fact] @@ -753,15 +765,29 @@ namespace FreeSql.Tests.Sqlite var subquery = select.ToSql(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); + Assert.Equal(@"SELECT a.""Id"" as1, a.""Clicks"" as2, a.""TypeGuid"" as3, a.""Title"" as4, a.""CreateTime"" as5, (SELECT avg(b.""Id"") + FROM ""tb_topic22"" b + limit 0,1) as6 +FROM ""tb_topic22"" a", subquery); var subqueryList = select.ToList(a => new { all = a, - count = select.Avg(b => b.Id) + count = select.As("b").Avg(b => b.Id) }); } [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""Id"", a.""Clicks"", a.""TypeGuid"", a.""Title"", a.""CreateTime"" +FROM ""tb_topic22"" a +WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title"" + FROM ""tb_topic22"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] public void As() { } diff --git a/FreeSql.Tests/FreeSql.Tests/g.cs b/FreeSql.Tests/FreeSql.Tests/g.cs index 0c8aac09..a4f06b7d 100644 --- a/FreeSql.Tests/FreeSql.Tests/g.cs +++ b/FreeSql.Tests/FreeSql.Tests/g.cs @@ -10,6 +10,7 @@ public class g static Lazy mysqlLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .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=2") + //.UseConnectionFactory(FreeSql.DataType.MySql, () => new MySql.Data.MySqlClient.MySqlConnection("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;")) .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseMonitorCommand( @@ -25,6 +26,7 @@ public class g NpgsqlConnection.GlobalTypeMapper.UseLegacyPostgis(); return new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") + //.UseConnectionFactory(FreeSql.DataType.PostgreSQL, () => new Npgsql.NpgsqlConnection("Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;")) .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseSyncStructureToLower(true) @@ -39,7 +41,9 @@ public class g static Lazy sqlserverLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3") + //.UseConnectionFactory(FreeSql.DataType.SqlServer, () => new System.Data.SqlClient.SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;")) //.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=192.168.164.129;uid=sa;pwd=123456;Initial Catalog=ds_shop;Pooling=true;Max Pool Size=3") + //.UseConnectionFactory(FreeSql.DataType.SqlServer, () => new System.Data.SqlClient.SqlConnection("Data Source=192.168.164.129;uid=sa;pwd=123456;Initial Catalog=ds_shop;Pooling=true;")) .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseMonitorCommand( @@ -52,6 +56,7 @@ public class g static Lazy oracleLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=2") + //.UseConnectionFactory(FreeSql.DataType.Oracle, () => new Oracle.ManagedDataAccess.Client.OracleConnection("user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;")) .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseLazyLoading(true) @@ -67,6 +72,16 @@ public class g static Lazy sqliteLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=2") + //.UseConnectionFactory(FreeSql.DataType.Sqlite, () => + //{ + // var conn = new System.Data.SQLite.SQLiteConnection(@"Data Source=|DataDirectory|\document.db;Pooling=true;"); + // //conn.Open(); + // //var cmd = conn.CreateCommand(); + // //cmd.CommandText = $"attach database [xxxtb.db] as [xxxtb];\r\n"; + // //cmd.ExecuteNonQuery(); + // //cmd.Dispose(); + // return conn; + //}) .UseAutoSyncStructure(true) //.UseGenerateCommandParameterWithLambda(true) .UseLazyLoading(true) diff --git a/FreeSql.sln b/FreeSql.sln index 32083dc2..f5f3b0f2 100644 --- a/FreeSql.sln +++ b/FreeSql.sln @@ -68,7 +68,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "orm_vs_net40", "Examples\or EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Generator", "Extensions\FreeSql.Generator\FreeSql.Generator.csproj", "{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}" EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "FreeSql.Tests.VB", "FreeSql.Tests.VB\FreeSql.Tests.VB.vbproj", "{A4FB811A-15EF-4E4C-AC15-826F9BB44E2D}" +Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "FreeSql.Tests.VB", "FreeSql.Tests.VB\FreeSql.Tests.VB.vbproj", "{A4FB811A-15EF-4E4C-AC15-826F9BB44E2D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index e0441819..51dcc983 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -28,7 +28,7 @@ - + diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 4346a314..1a33cd4d 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -613,7 +613,7 @@ - 使用连接串 + 使用连接串(推荐) 数据库类型 数据库连接串 @@ -627,6 +627,15 @@ 从数据库连接串 + + + 使用自定义数据库连接对象(放弃内置对象连接池技术) + + 数据库类型 + 数据库连接对象创建器 + 提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场 + + 【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改 @@ -2125,139 +2134,194 @@ - - - 查询,若使用读写分离,查询【从库】条件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 }) - - - - - - - + 可自定义解析表达式 + + + + + 自定义实体的配置,方便和多个 ORM 共同使用 + + + + + 自定义实体的属性配置,方便和多个 ORM 共同使用 + + + + + 增删查改,执行命令之前触发 + + + + + 增删查改,执行命令完成后触发 + + + + + CodeFirst迁移,执行之前触发 + + + + + CodeFirst迁移,执行完成触发 + + + + + Insert/Update自动值处理 + + + + + 内置解析功能,可辅助您进行解析 + + + + + 需要您解析的表达式 + + + + + 解析后的内容 + + + + + 实体类型 + + + + + 实体配置 + + + + + 索引配置 + + + + + 实体类型 + + + + + 实体的属性 + + + + + 实体的属性配置 + + + + + 标识符,可将 CurdBefore 与 CurdAfter 进行匹配 + + + + + 操作类型 + + + + + 实体类型 + + + + + 实体类型的元数据 + + + + + 执行的 SQL + + + + + 参数化命令 + + + + + 发生的错误 + + + + + 执行SQL命令,返回的结果 + + + + + 耗时(单位:Ticks) + + + + + 耗时(单位:毫秒) + + + + + 标识符,可将 SyncStructureBeforeEventArgs 与 SyncStructureAfterEventArgs 进行匹配 + + + + + 实体类型 + + + + + 执行的 SQL + + + + + 发生的错误 + + + + + 耗时(单位:Ticks) + + + + + 耗时(单位:毫秒) + + + + + 类型 + + + + + 属性列的元数据 + + + + + 反射的属性信息 + + + + + 获取实体的属性值,也可以设置实体的属性新值 + + + + + 【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改 @@ -2848,160 +2912,3 @@ -unc{``0,System.Boolean}},System.Boolean,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})"> - - 使用 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/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index fd1db807..8e843a9b 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -12,6 +12,7 @@ namespace FreeSql DataType _dataType; string _masterConnectionString; string[] _slaveConnectionString; + Func _connectionFactory; bool _isAutoSyncStructure = false; bool _isSyncStructureToLower = false; bool _isSyncStructureToUpper = false; @@ -25,7 +26,7 @@ namespace FreeSql Type _providerType = null; /// - /// 使用连接串 + /// 使用连接串(推荐) /// /// 数据库类型 /// 数据库连接串 @@ -33,6 +34,7 @@ namespace FreeSql /// public FreeSqlBuilder UseConnectionString(DataType dataType, string connectionString, Type providerType = null) { + if (_connectionFactory != null) throw new Exception("已经指定了 UseConnectionFactory,不能再指定 UseConnectionString"); _dataType = dataType; _masterConnectionString = connectionString; _providerType = providerType; @@ -45,10 +47,27 @@ namespace FreeSql /// public FreeSqlBuilder UseSlave(params string[] slaveConnectionString) { + if (_connectionFactory != null) throw new Exception("已经指定了 UseConnectionFactory,不能再指定 UseSlave"); _slaveConnectionString = slaveConnectionString; return this; } /// + /// 使用自定义数据库连接对象(放弃内置对象连接池技术) + /// + /// 数据库类型 + /// 数据库连接对象创建器 + /// 提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场 + /// + public FreeSqlBuilder UseConnectionFactory(DataType dataType, Func connectionFactory, Type providerType = null) + { + if (string.IsNullOrEmpty(_masterConnectionString) == false) throw new Exception("已经指定了 UseConnectionString,不能再指定 UseConnectionFactory"); + if (_slaveConnectionString?.Any() == true) throw new Exception("已经指定了 UseSlave,不能再指定 UseConnectionFactory"); + _dataType = dataType; + _connectionFactory = connectionFactory; + _providerType = providerType; + return this; + } + /// /// 【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改 /// /// true:运行时检查自动同步结构, false:不同步结构 @@ -149,7 +168,7 @@ namespace FreeSql public IFreeSql Build() => Build(); public IFreeSql Build() { - if (string.IsNullOrEmpty(_masterConnectionString)) throw new Exception("参数 masterConnectionString 不可为空,请检查 UseConnectionString"); + if (string.IsNullOrEmpty(_masterConnectionString) && _connectionFactory == null) throw new Exception("参数 masterConnectionString 不可为空,请检查 UseConnectionString"); IFreeSql ret = null; var type = _providerType; if (type?.IsGenericType == true) type = type.MakeGenericType(typeof(TMark)); @@ -208,7 +227,7 @@ namespace FreeSql default: throw new Exception("未指定 UseConnectionString"); } } - ret = Activator.CreateInstance(type, new object[] { _masterConnectionString, _slaveConnectionString }) as IFreeSql; + ret = Activator.CreateInstance(type, new object[] { _masterConnectionString, _slaveConnectionString, _connectionFactory }) as IFreeSql; if (ret != null) { ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure; diff --git a/FreeSql/Interface/IAdo.cs b/FreeSql/Interface/IAdo.cs index b42cb61e..57670ee0 100644 --- a/FreeSql/Interface/IAdo.cs +++ b/FreeSql/Interface/IAdo.cs @@ -14,11 +14,11 @@ namespace FreeSql /// /// 主库连接池 /// - ObjectPool MasterPool { get; } + IObjectPool MasterPool { get; } /// /// 从库连接池 /// - List> SlavePools { get; } + List> SlavePools { get; } /// /// 监视数据库命令对象(执行前,调试) /// diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index f3cc5c5b..e43904f5 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -660,6 +660,7 @@ namespace FreeSql.Internal case "Min": case "Max": case "Avg": + case "ToList": //where in case "First": var anyArgs = exp3.Arguments; var exp3Stack = new Stack(); @@ -732,7 +733,8 @@ namespace FreeSql.Internal if (fsql == null) fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke(); fsqlType = fsql?.GetType(); if (fsqlType == null) break; - fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1); + if (exp3.Method.Name != "ToList") + fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1); fsqltables = fsqlType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(fsql) as List; //fsqltables[0].Alias = $"{tsc._tables[0].Alias}_{fsqltables[0].Alias}"; if (fsqltables != tsc._tables) @@ -915,6 +917,7 @@ namespace FreeSql.Internal if (string.IsNullOrEmpty(sqlSum) == false) return $"({sqlSum.Replace("\r\n", "\r\n\t")})"; break; + case "ToList": case "First": var tscClone2 = tsc.CloneDisableDiyParse(); tscClone2.isDisableDiyParse = false; diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs index a8048150..840f6ca1 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs @@ -14,7 +14,7 @@ namespace FreeSql.Internal.CommonProvider public abstract partial class AdoProvider : IAdo, IDisposable { - protected abstract void ReturnConnection(ObjectPool pool, Object conn, Exception ex); + protected abstract void ReturnConnection(IObjectPool pool, Object conn, Exception ex); protected abstract DbCommand CreateCommand(); protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj); public Action AopCommandExecuting { get; set; } @@ -22,8 +22,8 @@ namespace FreeSql.Internal.CommonProvider protected bool IsTracePerformance => AopCommandExecuted != null; - public ObjectPool MasterPool { get; protected set; } - public List> SlavePools { get; } = new List>(); + public IObjectPool MasterPool { get; protected set; } + public List> SlavePools { get; } = new List>(); public DataType DataType { get; } protected CommonUtils _util { get; set; } protected int slaveUnavailables = 0; @@ -35,7 +35,7 @@ namespace FreeSql.Internal.CommonProvider this.DataType = dataType; } - void LoggerException(ObjectPool pool, (DbCommand cmd, bool isclose) pc, Exception e, DateTime dt, StringBuilder logtxt, bool isThrowException = true) + void LoggerException(IObjectPool pool, (DbCommand cmd, bool isclose) pc, Exception e, DateTime dt, StringBuilder logtxt, bool isThrowException = true) { var cmd = pc.cmd; if (pc.isclose) pc.cmd.Connection.Close(); @@ -76,7 +76,11 @@ namespace FreeSql.Internal.CommonProvider AopCommandExecuted?.Invoke(cmd, log.ToString()); cmd.Parameters.Clear(); - if (isThrowException) throw e; + if (isThrowException) + { + cmd.Dispose(); + throw e; + } } internal Dictionary GetQueryTypeProperties(Type type) @@ -515,7 +519,7 @@ namespace FreeSql.Internal.CommonProvider //查从库 this.SlavePools : ( //查主库 - slaveUnavailables == this.SlavePools.Count ? new List>() : + slaveUnavailables == this.SlavePools.Count ? new List>() : //查从库可用 this.SlavePools.Where(sp => sp.IsAvailable).ToList()); if (availables.Any()) @@ -556,6 +560,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); ExecuteReaderMultiple(multipleResult, connection, transaction, readerHander, cmdType, cmdText, cmdParms); return; } @@ -618,6 +623,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); } public object[][] ExecuteArray(string cmdText, object parms = null) => ExecuteArray(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); public object[][] ExecuteArray(DbTransaction transaction, string cmdText, object parms = null) => ExecuteArray(null, transaction, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -708,6 +714,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); return val; } public object ExecuteScalar(string cmdText, object parms = null) => ExecuteScalar(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -743,6 +750,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); return val; } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs index a9b154ae..63e50246 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs @@ -448,7 +448,7 @@ namespace FreeSql.Internal.CommonProvider //查从库 this.SlavePools : ( //查主库 - slaveUnavailables == this.SlavePools.Count ? new List>() : + slaveUnavailables == this.SlavePools.Count ? new List>() : //查从库可用 this.SlavePools.Where(sp => sp.IsAvailable).ToList()); if (availables.Any()) @@ -489,6 +489,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); await ExecuteReaderMultipleAsync(multipleResult, connection, transaction, readerHander, cmdType, cmdText, cmdParms); return; } @@ -551,6 +552,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); } public Task ExecuteArrayAsync(string cmdText, object parms = null) => ExecuteArrayAsync(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); public Task ExecuteArrayAsync(DbTransaction transaction, string cmdText, object parms = null) => ExecuteArrayAsync(null, transaction, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -642,6 +644,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); return val; } public Task ExecuteScalarAsync(string cmdText, object parms = null) => ExecuteScalarAsync(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -677,6 +680,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); + pc.cmd.Dispose(); return val; } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs index 7da093e8..df0b0741 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderTransaction.cs @@ -136,7 +136,7 @@ namespace FreeSql.Internal.CommonProvider } catch { } - ObjectPool[] pools = null; + IObjectPool[] pools = null; for (var a = 0; a < 10; a++) { try diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs b/FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs new file mode 100644 index 00000000..5d2d931b --- /dev/null +++ b/FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs @@ -0,0 +1,134 @@ +using SafeObjectPool; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FreeSql.Internal.CommonProvider +{ + public class DbConnectionPool : IObjectPool + { + internal DataType _dataType; + internal Func _connectionFactory; + int _id; + public DbConnectionPool(DataType dataType, Func connectionFactory) + { + _dataType = dataType; + _connectionFactory = connectionFactory; + Policy = new DbConnectionPoolPolicy(this); + } + + public IPolicy Policy { get; } + + public bool IsAvailable => true; + public Exception UnavailableException => null; + public DateTime? UnavailableTime => null; + public string Statistics => "throw new NotImplementedException()"; + public string StatisticsFullily => "throw new NotImplementedException()"; + + public void Dispose() + { + } + + public Object Get(TimeSpan? timeout = null) + { + var conn = _connectionFactory(); + if (conn.State != ConnectionState.Open) + conn.Open(); + return Object.InitWith(this, Interlocked.Increment(ref _id), conn); + } + +#if net40 +#else + async public Task> GetAsync() + { + var conn = _connectionFactory(); + if (conn.State != ConnectionState.Open) + await conn.OpenAsync(); + return Object.InitWith(this, Interlocked.Increment(ref _id), conn); + } +#endif + + public void Return(Object obj, bool isReset = false) + { + if (obj == null) return; + Policy.OnDestroy(obj.Value); + } + + public bool SetUnavailable(Exception exception) + { + throw new NotImplementedException(); + } + } + + internal class DbConnectionPoolPolicy : IPolicy + { + DbConnectionPool Pool; + public DbConnectionPoolPolicy(DbConnectionPool pool) + { + this.Pool = pool; + } + + public string Name { get; set; } = typeof(DbConnectionPoolPolicy).GetType().FullName; + public int PoolSize { get; set; } = 1000; + public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); + public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(50); + public int AsyncGetCapacity { get; set; } = 10000; + public bool IsThrowGetTimeoutException { get; set; } = true; + public int CheckAvailableInterval { get; set; } = 5; + + public DbConnection OnCreate() + { + var conn = Pool._connectionFactory(); + if (conn.State != ConnectionState.Open) + conn.Open(); + return conn; + } + + public void OnDestroy(DbConnection obj) + { + if (obj != null) + { + if (obj.State != ConnectionState.Closed) + obj.Close(); + //obj.Dispose(); + } + } + + public void OnGet(Object obj) + { + } + +#if net40 +#else + public Task OnGetAsync(Object obj) + { + return Task.FromResult(true); + } +#endif + + public void OnGetTimeout() + { + } + + public void OnReturn(Object obj) + { + } + + public bool OnCheckAvailable(Object obj) + { + return true; + } + + public void OnAvailable() + { + } + + public void OnUnavailable() + { + } + } +} diff --git a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs index c101e092..62ec1bd3 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs @@ -14,9 +14,14 @@ namespace FreeSql.MySql { public MySqlAdo() : base(DataType.MySql) { } - public MySqlAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.MySql) + public MySqlAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.MySql) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.MySql, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new MySqlConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -59,9 +64,11 @@ namespace FreeSql.MySql return new MySqlCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as MySqlConnectionPool).Return(conn, ex); + var rawPool = pool as MySqlConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.MySql/MySqlProvider.cs b/Providers/FreeSql.Provider.MySql/MySqlProvider.cs index edfe0054..f1b146d0 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlProvider.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlProvider.cs @@ -55,12 +55,12 @@ namespace FreeSql.MySql public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public MySqlProvider(string masterConnectionString, string[] slaveConnectionString) + public MySqlProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new MySqlUtils(this); this.InternalCommonExpression = new MySqlExpression(this.InternalCommonUtils); - this.Ado = new MySqlAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new MySqlAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new MySqlDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengAdo.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengAdo.cs index ec2338a2..ed749b48 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengAdo.cs @@ -12,10 +12,15 @@ namespace FreeSql.Odbc.Dameng { class OdbcDamengAdo : FreeSql.Internal.CommonProvider.AdoProvider { - public OdbcDamengAdo() : base(DataType.Oracle) { } - public OdbcDamengAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Oracle) + public OdbcDamengAdo() : base(DataType.OdbcDameng) { } + public OdbcDamengAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.OdbcDameng) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.OdbcDameng, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcDamengConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -57,9 +62,11 @@ namespace FreeSql.Odbc.Dameng return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcDamengConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcDamengConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs index 81a601bb..f6d7eede 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs @@ -21,9 +21,7 @@ namespace FreeSql.Odbc.Dameng public OdbcDamengConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) { - var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); - if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); - this.UserId = userIdMatch.Groups[2].Value.Trim().ToUpper(); + this.UserId = OdbcDamengConnectionPool.GetUserId(connectionString); var policy = new OdbcOracleConnectionPoolPolicy { @@ -37,6 +35,13 @@ namespace FreeSql.Odbc.Dameng this.unavailableHandler = unavailableHandler; } + public static string GetUserId(string connectionString) + { + var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); + if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); + return userIdMatch.Groups[2].Value.Trim().ToUpper(); + } + public void Return(Object obj, Exception exception, bool isRecreate = false) { if (exception != null && exception is OdbcException) diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs index 99d486fd..09a14594 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs @@ -77,7 +77,12 @@ namespace FreeSql.Odbc.Dameng protected override string GetComparisonDDLStatements(params (Type entityType, string tableName)[] objects) { - var userId = (_orm.Ado.MasterPool as OdbcDamengConnectionPool).UserId; + var userId = (_orm.Ado.MasterPool as OdbcDamengConnectionPool)?.UserId; + if (string.IsNullOrEmpty(userId)) + using (var conn = _orm.Ado.MasterPool.Get()) + { + userId = OdbcDamengConnectionPool.GetUserId(conn.Value.ConnectionString); + } var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列:列,表,自增 var seqnameDel = new List(); //要删除的序列+触发器 diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs index 97c84c96..c1da688a 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs @@ -28,12 +28,12 @@ namespace FreeSql.Odbc.Dameng public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OdbcDamengProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcDamengProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcDamengUtils(this); this.InternalCommonExpression = new OdbcDamengExpression(this.InternalCommonUtils); - this.Ado = new OdbcDamengAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcDamengAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OdbcDamengDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs index 27352355..69fdce7d 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs @@ -13,9 +13,14 @@ namespace FreeSql.Odbc.Default class OdbcAdo : FreeSql.Internal.CommonProvider.AdoProvider { public OdbcAdo() : base(DataType.Odbc) { } - public OdbcAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Odbc) + public OdbcAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.Odbc) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.Odbc, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -60,9 +65,11 @@ namespace FreeSql.Odbc.Default return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs index d4104e30..9406b549 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcProvider.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Threading; @@ -37,12 +38,12 @@ namespace FreeSql.Odbc.Default /// /// /// 适配器 - public OdbcProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcUtils(this); this.InternalCommonExpression = new OdbcExpression(this.InternalCommonUtils); - this.Ado = new OdbcAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.CodeFirst = new OdbcCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseAdo/__OdbcGBaseAdo.cs b/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseAdo/__OdbcGBaseAdo.cs index c4c215f2..8129aafe 100644 --- a/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseAdo/__OdbcGBaseAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseAdo/__OdbcGBaseAdo.cs @@ -14,9 +14,14 @@ namespace FreeSql.Odbc.GBase class OdbcGBaseAdo : FreeSql.Internal.CommonProvider.AdoProvider { public OdbcGBaseAdo() : base(DataType.PostgreSQL) { } - public OdbcGBaseAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.PostgreSQL) + public OdbcGBaseAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.PostgreSQL) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.PostgreSQL, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcGBaseConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -58,9 +63,11 @@ namespace FreeSql.Odbc.GBase return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcGBaseConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcGBaseConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseProvider.cs b/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseProvider.cs index 66e28e82..0d797f6f 100644 --- a/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/GBase/OdbcGBaseProvider.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.CommonProvider; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Threading; namespace FreeSql.Odbc.GBase @@ -31,12 +32,12 @@ namespace FreeSql.Odbc.GBase public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OdbcGBaseProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcGBaseProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcGBaseUtils(this); this.InternalCommonExpression = new OdbcGBaseExpression(this.InternalCommonUtils); - this.Ado = new OdbcGBaseAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcGBaseAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OdbcGBaseDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs index 8c6f5c24..7f454fb0 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs @@ -13,10 +13,15 @@ namespace FreeSql.Odbc.MySql class OdbcMySqlAdo : FreeSql.Internal.CommonProvider.AdoProvider { - public OdbcMySqlAdo() : base(DataType.MySql) { } - public OdbcMySqlAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.MySql) + public OdbcMySqlAdo() : base(DataType.OdbcMySql) { } + public OdbcMySqlAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.OdbcMySql) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.OdbcMySql, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcMySqlConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -57,9 +62,11 @@ namespace FreeSql.Odbc.MySql return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcMySqlConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcMySqlConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlProvider.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlProvider.cs index 95b21a6b..a0bb6347 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlProvider.cs @@ -33,12 +33,12 @@ namespace FreeSql.Odbc.MySql public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OdbcMySqlProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcMySqlProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcMySqlUtils(this); this.InternalCommonExpression = new OdbcMySqlExpression(this.InternalCommonUtils); - this.Ado = new OdbcMySqlAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcMySqlAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OdbcMySqlDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs index 98e7921a..b3d53183 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs @@ -12,10 +12,15 @@ namespace FreeSql.Odbc.Oracle { class OdbcOracleAdo : FreeSql.Internal.CommonProvider.AdoProvider { - public OdbcOracleAdo() : base(DataType.Oracle) { } - public OdbcOracleAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Oracle) + public OdbcOracleAdo() : base(DataType.OdbcOracle) { } + public OdbcOracleAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.OdbcOracle) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.OdbcOracle, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcOracleConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -57,9 +62,11 @@ namespace FreeSql.Odbc.Oracle return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcOracleConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcOracleConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs index 7ccfa7bd..31d23008 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleConnectionPool.cs @@ -21,9 +21,7 @@ namespace FreeSql.Odbc.Oracle public OdbcOracleConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) { - var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); - if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); - this.UserId = userIdMatch.Groups[2].Value.Trim().ToUpper(); + this.UserId = OdbcOracleConnectionPool.GetUserId(connectionString); var policy = new OdbcOracleConnectionPoolPolicy { @@ -37,6 +35,13 @@ namespace FreeSql.Odbc.Oracle this.unavailableHandler = unavailableHandler; } + public static string GetUserId(string connectionString) + { + var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); + if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); + return userIdMatch.Groups[2].Value.Trim().ToUpper(); + } + public void Return(Object obj, Exception exception, bool isRecreate = false) { if (exception != null && exception is OdbcException) diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleCodeFirst.cs index ad61cdb9..eece275f 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleCodeFirst.cs @@ -77,7 +77,12 @@ namespace FreeSql.Odbc.Oracle protected override string GetComparisonDDLStatements(params (Type entityType, string tableName)[] objects) { - var userId = (_orm.Ado.MasterPool as OdbcOracleConnectionPool).UserId; + var userId = (_orm.Ado.MasterPool as OdbcOracleConnectionPool)?.UserId; + if (string.IsNullOrEmpty(userId)) + using (var conn = _orm.Ado.MasterPool.Get()) + { + userId = OdbcOracleConnectionPool.GetUserId(conn.Value.ConnectionString); + } var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列:列,表,自增 var seqnameDel = new List(); //要删除的序列+触发器 diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleProvider.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleProvider.cs index e82bc16d..47b16b74 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleProvider.cs @@ -28,12 +28,12 @@ namespace FreeSql.Odbc.Oracle public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OdbcOracleProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcOracleProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcOracleUtils(this); this.InternalCommonExpression = new OdbcOracleExpression(this.InternalCommonUtils); - this.Ado = new OdbcOracleAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcOracleAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OdbcOracleDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs index 0777ffb8..cdd1269e 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs @@ -13,10 +13,15 @@ namespace FreeSql.Odbc.PostgreSQL { class OdbcPostgreSQLAdo : FreeSql.Internal.CommonProvider.AdoProvider { - public OdbcPostgreSQLAdo() : base(DataType.PostgreSQL) { } - public OdbcPostgreSQLAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.PostgreSQL) + public OdbcPostgreSQLAdo() : base(DataType.OdbcPostgreSQL) { } + public OdbcPostgreSQLAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.OdbcPostgreSQL) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.OdbcPostgreSQL, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcPostgreSQLConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -58,9 +63,11 @@ namespace FreeSql.Odbc.PostgreSQL return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcPostgreSQLConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcPostgreSQLConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLProvider.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLProvider.cs index d858489a..dee8daae 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLProvider.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.CommonProvider; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Threading; namespace FreeSql.Odbc.PostgreSQL @@ -31,12 +32,12 @@ namespace FreeSql.Odbc.PostgreSQL public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OdbcPostgreSQLProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcPostgreSQLProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcPostgreSQLUtils(this); this.InternalCommonExpression = new OdbcPostgreSQLExpression(this.InternalCommonUtils); - this.Ado = new OdbcPostgreSQLAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcPostgreSQLAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OdbcPostgreSQLDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs index 20e197c6..a9661dc8 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs @@ -13,10 +13,15 @@ namespace FreeSql.Odbc.SqlServer { class OdbcSqlServerAdo : FreeSql.Internal.CommonProvider.AdoProvider { - public OdbcSqlServerAdo() : base(DataType.SqlServer) { } - public OdbcSqlServerAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.SqlServer) + public OdbcSqlServerAdo() : base(DataType.OdbcSqlServer) { } + public OdbcSqlServerAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.OdbcSqlServer) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.OdbcSqlServer, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OdbcSqlServerConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -73,9 +78,11 @@ namespace FreeSql.Odbc.SqlServer return new OdbcCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OdbcSqlServerConnectionPool).Return(conn, ex); + var rawPool = pool as OdbcSqlServerConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerProvider.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerProvider.cs index faf7847a..5d3fd7bf 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerProvider.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.CommonProvider; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Threading; namespace FreeSql.Odbc.SqlServer @@ -27,12 +28,12 @@ namespace FreeSql.Odbc.SqlServer public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OdbcSqlServerProvider(string masterConnectionString, string[] slaveConnectionString) + public OdbcSqlServerProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OdbcSqlServerUtils(this); this.InternalCommonExpression = new OdbcSqlServerExpression(this.InternalCommonUtils); - this.Ado = new OdbcSqlServerAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OdbcSqlServerAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OdbcSqlServerDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs index 3c637833..289b95f4 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs @@ -13,9 +13,14 @@ namespace FreeSql.Oracle class OracleAdo : FreeSql.Internal.CommonProvider.AdoProvider { public OracleAdo() : base(DataType.Oracle) { } - public OracleAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Oracle) + public OracleAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.Oracle) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.Oracle, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new OracleConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -59,9 +64,11 @@ namespace FreeSql.Oracle return cmd; } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as OracleConnectionPool).Return(conn, ex); + var rawPool = pool as OracleConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs index cf65eb94..f28debbc 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleConnectionPool.cs @@ -21,9 +21,7 @@ namespace FreeSql.Oracle public OracleConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) { - var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); - if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); - this.UserId = userIdMatch.Groups[2].Value.Trim().ToUpper(); + this.UserId = OracleConnectionPool.GetUserId(connectionString); var policy = new OracleConnectionPoolPolicy { @@ -37,6 +35,13 @@ namespace FreeSql.Oracle this.unavailableHandler = unavailableHandler; } + public static string GetUserId(string connectionString) + { + var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); + if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); + return userIdMatch.Groups[2].Value.Trim().ToUpper(); + } + public void Return(Object obj, Exception exception, bool isRecreate = false) { if (exception != null && exception is OracleException) diff --git a/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs b/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs index e408452f..85a273e7 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs @@ -78,7 +78,12 @@ namespace FreeSql.Oracle protected override string GetComparisonDDLStatements(params (Type entityType, string tableName)[] objects) { - var userId = (_orm.Ado.MasterPool as OracleConnectionPool).UserId; + var userId = (_orm.Ado.MasterPool as OracleConnectionPool)?.UserId; + if (string.IsNullOrEmpty(userId)) + using (var conn = _orm.Ado.MasterPool.Get()) + { + userId = OracleConnectionPool.GetUserId(conn.Value.ConnectionString); + } var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列:列,表,自增 var seqnameDel = new List(); //要删除的序列+触发器 diff --git a/Providers/FreeSql.Provider.Oracle/OracleProvider.cs b/Providers/FreeSql.Provider.Oracle/OracleProvider.cs index 6be0984e..9a7bebdc 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleProvider.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleProvider.cs @@ -29,12 +29,12 @@ namespace FreeSql.Oracle public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public OracleProvider(string masterConnectionString, string[] slaveConnectionString) + public OracleProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new OracleUtils(this); this.InternalCommonExpression = new OracleExpression(this.InternalCommonUtils); - this.Ado = new OracleAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new OracleAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new OracleDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs index f1600c24..1dca64d1 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs @@ -15,9 +15,14 @@ namespace FreeSql.PostgreSQL class PostgreSQLAdo : FreeSql.Internal.CommonProvider.AdoProvider { public PostgreSQLAdo() : base(DataType.PostgreSQL) { } - public PostgreSQLAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.PostgreSQL) + public PostgreSQLAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.PostgreSQL) { - base._util = util; + base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.PostgreSQL, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new PostgreSQLConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -75,9 +80,11 @@ namespace FreeSql.PostgreSQL return new NpgsqlCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as PostgreSQLConnectionPool).Return(conn, ex); + var rawPool = pool as PostgreSQLConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs index a900c60a..8471653f 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs @@ -82,12 +82,12 @@ namespace FreeSql.PostgreSQL public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public PostgreSQLProvider(string masterConnectionString, string[] slaveConnectionString) + public PostgreSQLProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new PostgreSQLUtils(this); this.InternalCommonExpression = new PostgreSQLExpression(this.InternalCommonUtils); - this.Ado = new PostgreSQLAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new PostgreSQLAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new PostgreSQLDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs index 2d898e7a..b12cdf10 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs @@ -14,9 +14,14 @@ namespace FreeSql.SqlServer class SqlServerAdo : FreeSql.Internal.CommonProvider.AdoProvider { public SqlServerAdo() : base(DataType.SqlServer) { } - public SqlServerAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.SqlServer) + public SqlServerAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.SqlServer) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.SqlServer, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new SqlServerConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -73,9 +78,11 @@ namespace FreeSql.SqlServer return new SqlCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as SqlServerConnectionPool).Return(conn, ex); + var rawPool = pool as SqlServerConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerProvider.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerProvider.cs index 0de7d235..afaf697b 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerProvider.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerProvider.cs @@ -4,6 +4,7 @@ using FreeSql.SqlServer.Curd; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Threading; namespace FreeSql.SqlServer @@ -28,12 +29,12 @@ namespace FreeSql.SqlServer public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public SqlServerProvider(string masterConnectionString, string[] slaveConnectionString) + public SqlServerProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new SqlServerUtils(this); this.InternalCommonExpression = new SqlServerExpression(this.InternalCommonUtils); - this.Ado = new SqlServerAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new SqlServerAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.DbFirst = new SqlServerDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs index d57c74ec..d589b9b4 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs @@ -12,9 +12,14 @@ namespace FreeSql.Sqlite class SqliteAdo : FreeSql.Internal.CommonProvider.AdoProvider { public SqliteAdo() : base(DataType.Sqlite) { } - public SqliteAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Sqlite) + public SqliteAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.Sqlite) { base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.Sqlite, connectionFactory); + return; + } if (!string.IsNullOrEmpty(masterConnectionString)) MasterPool = new SqliteConnectionPool("主库", masterConnectionString, null, null); if (slaveConnectionStrings != null) @@ -55,9 +60,11 @@ namespace FreeSql.Sqlite return AdonetPortable.GetSqliteCommand(); } - protected override void ReturnConnection(ObjectPool pool, Object conn, Exception ex) + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) { - (pool as SqliteConnectionPool).Return(conn, ex); + var rawPool = pool as SqliteConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); } protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs index bc915c72..791fdb02 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteConnectionPool.cs @@ -224,7 +224,10 @@ namespace FreeSql.Sqlite { try { - PingCommand(that).ExecuteNonQuery(); + using (var cmd = PingCommand(that)) + { + cmd.ExecuteNonQuery(); + } return true; } catch @@ -247,6 +250,7 @@ namespace FreeSql.Sqlite var cmd = that.CreateCommand(); cmd.CommandText = sb.ToString(); cmd.ExecuteNonQuery(); + cmd.Dispose(); } } @@ -256,7 +260,10 @@ namespace FreeSql.Sqlite { try { - await PingCommand(that).ExecuteNonQueryAsync(); + using (var cmd = PingCommand(that)) + { + await cmd.ExecuteNonQueryAsync(); + } return true; } catch @@ -279,6 +286,7 @@ namespace FreeSql.Sqlite var cmd = that.CreateCommand(); cmd.CommandText = sb.ToString(); await cmd.ExecuteNonQueryAsync(); + cmd.Dispose(); } } #endif diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteProvider.cs b/Providers/FreeSql.Provider.Sqlite/SqliteProvider.cs index ba92b82f..5e4a8abb 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteProvider.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteProvider.cs @@ -29,12 +29,12 @@ namespace FreeSql.Sqlite public IAop Aop { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst => null; - public SqliteProvider(string masterConnectionString, string[] slaveConnectionString) + public SqliteProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) { this.InternalCommonUtils = new SqliteUtils(this); this.InternalCommonExpression = new SqliteExpression(this.InternalCommonUtils); - this.Ado = new SqliteAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); + this.Ado = new SqliteAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); this.Aop = new AopProvider(); this.CodeFirst = new SqliteCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);