From ec6d482321c38a4606d2df054ab838a0f43d5170 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Mon, 14 Jan 2019 14:15:46 +0800 Subject: [PATCH] update --- .../FreeSql.Tests.PerformanceTests.csproj | 21 +++++ .../MySqlAdoTest.cs | 91 +++++++++++++++++++ FreeSql.Tests.PerformanceTests/g.cs | 39 ++++++++ FreeSql.Tests/FreeSql.Tests.csproj | 4 +- FreeSql.Tests/MySql/MySqlAdo/MySqlAdoTest.cs | 5 - .../Oracle/OracleAdo/OracleAdoTest.cs | 5 - .../PostgreSQLAdo/PostgreSQLAdoTest.cs | 5 - .../SqlServerAdo/SqlServerAdoTest.cs | 5 - .../Sqlite/SqliteAdo/SqliteAdoTest.cs | 6 -- FreeSql.sln | 14 +++ FreeSql/FreeSql.csproj | 5 +- FreeSql/FreeSqlBuilder.cs | 2 +- FreeSql/Interface/IAdo.cs | 8 +- .../CommonProvider/AdoProvider/AdoProvider.cs | 17 ++-- FreeSql/Internal/Utils.cs | 2 +- readme.md | 27 ++++++ 16 files changed, 212 insertions(+), 44 deletions(-) create mode 100644 FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj create mode 100644 FreeSql.Tests.PerformanceTests/MySqlAdoTest.cs create mode 100644 FreeSql.Tests.PerformanceTests/g.cs diff --git a/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj b/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj new file mode 100644 index 00000000..3e848441 --- /dev/null +++ b/FreeSql.Tests.PerformanceTests/FreeSql.Tests.PerformanceTests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + diff --git a/FreeSql.Tests.PerformanceTests/MySqlAdoTest.cs b/FreeSql.Tests.PerformanceTests/MySqlAdoTest.cs new file mode 100644 index 00000000..1d1f5754 --- /dev/null +++ b/FreeSql.Tests.PerformanceTests/MySqlAdoTest.cs @@ -0,0 +1,91 @@ +using FreeSql.DataAnnotations; +using System; +using System.Diagnostics; +using System.Text; +using Xunit; +using Dapper; +using System.Linq; +using System.Collections.Generic; + +namespace FreeSql.Tests.PerformanceTest { + public class MySqlAdoTest { + + [Fact] + public void Query() { + var sb = new StringBuilder(); + var time = new Stopwatch(); + + time.Restart(); + List dplist1 = null; + using (var conn = g.mysql.Ado.MasterPool.Get()) { + dplist1 = Dapper.SqlMapper.Query(conn.Value, "select * from song").ToList(); + } + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {dplist1.Count}; ORM: Dapper"); + + time.Restart(); + List<(int, string, string)> dplist2 = null; + using (var conn = g.mysql.Ado.MasterPool.Get()) { + dplist2 = Dapper.SqlMapper.Query<(int, string, string)>(conn.Value, "select * from song").ToList(); + } + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Tuple Counts: {dplist2.Count}; ORM: Dapper"); + + time.Restart(); + List dplist3 = null; + using (var conn = g.mysql.Ado.MasterPool.Get()) { + dplist3 = Dapper.SqlMapper.Query(conn.Value, "select * from song").ToList(); + } + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Dynamic Counts: {dplist3.Count}; ORM: Dapper"); + + + + + time.Restart(); + var t3 = g.mysql.Ado.Query("select * from song"); + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {t3.Count}; ORM: FreeSql*"); + + time.Restart(); + var t4 = g.mysql.Ado.Query<(int, string, string)>("select * from song"); + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Tuple Counts: {t4.Count}; ORM: FreeSql*"); + + time.Restart(); + var t5 = g.mysql.Ado.Query("select * from song"); + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Dynamic Counts: {t3.Count}; ORM: FreeSql*"); + + } + + [Fact] + public void ToList() { + var sb = new StringBuilder(); + var time = new Stopwatch(); + + time.Restart(); + List dplist1 = null; + using (var conn = g.mysql.Ado.MasterPool.Get()) { + dplist1 = Dapper.SqlMapper.Query(conn.Value, "select * from song").ToList(); + } + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; Query Entity Counts: {dplist1.Count}; ORM: Dapper"); + + + time.Restart(); + var t3 = g.mysql.Select().ToList(); + time.Stop(); + sb.AppendLine($"Elapsed: {time.Elapsed}; ToList Entity Counts: {t3.Count}; ORM: FreeSql*"); + } + + [Table(Name = "song")] + class xxx { + public int Id { get; set; } + public string Title { get; set; } + public string Url { get; set; } + public DateTime Create_time { get; set; } + public bool Is_deleted { get; set; } + } + } +} diff --git a/FreeSql.Tests.PerformanceTests/g.cs b/FreeSql.Tests.PerformanceTests/g.cs new file mode 100644 index 00000000..f1cafbb0 --- /dev/null +++ b/FreeSql.Tests.PerformanceTests/g.cs @@ -0,0 +1,39 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; + + +public class g { + + public static IFreeSql mysql = 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=10") + .UseLogger(new LoggerFactory().CreateLogger("FreeSql.MySql")) + .UseAutoSyncStructure(false) + .Build(); + + //public static IFreeSql sqlserver = new FreeSql.FreeSqlBuilder() + // .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=cms;Pooling=true;Max Pool Size=10") + // .UseLogger(new LoggerFactory().CreateLogger("FreeSql.SqlServer")) + // .UseAutoSyncStructure(false) + // .Build(); + + //public static IFreeSql pgsql = 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=10") + // .UseLogger(new LoggerFactory().CreateLogger("FreeSql.PostgreSQL")) + // .UseAutoSyncStructure(false) + // .UseSyncStructureToLower(true) + // .Build(); + + //public static IFreeSql oracle = 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=10") + // .UseLogger(new LoggerFactory().CreateLogger("FreeSql.Oracle")) + // .UseAutoSyncStructure(false) + // .Build(); + + //public static IFreeSql sqlite = new FreeSql.FreeSqlBuilder() + // .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10") + // .UseLogger(new LoggerFactory().CreateLogger("FreeSql.Sqlite")) + // .UseAutoSyncStructure(false) + // .Build(); +} diff --git a/FreeSql.Tests/FreeSql.Tests.csproj b/FreeSql.Tests/FreeSql.Tests.csproj index f8c639cb..64205046 100644 --- a/FreeSql.Tests/FreeSql.Tests.csproj +++ b/FreeSql.Tests/FreeSql.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 @@ -15,5 +15,5 @@ - + diff --git a/FreeSql.Tests/MySql/MySqlAdo/MySqlAdoTest.cs b/FreeSql.Tests/MySql/MySqlAdo/MySqlAdoTest.cs index 83812d4f..aeef6f44 100644 --- a/FreeSql.Tests/MySql/MySqlAdo/MySqlAdoTest.cs +++ b/FreeSql.Tests/MySql/MySqlAdo/MySqlAdoTest.cs @@ -14,11 +14,6 @@ namespace FreeSql.Tests.MySql { var t2 = g.mysql.Ado.SlavePools.Count; } - [Fact] - public void IsTracePerformance() { - Assert.True(g.mysql.Ado.IsTracePerformance); - } - [Fact] public void ExecuteReader() { diff --git a/FreeSql.Tests/Oracle/OracleAdo/OracleAdoTest.cs b/FreeSql.Tests/Oracle/OracleAdo/OracleAdoTest.cs index 13c2e48f..6b74b4c9 100644 --- a/FreeSql.Tests/Oracle/OracleAdo/OracleAdoTest.cs +++ b/FreeSql.Tests/Oracle/OracleAdo/OracleAdoTest.cs @@ -14,11 +14,6 @@ namespace FreeSql.Tests.Oracle { var t2 = g.oracle.Ado.SlavePools.Count; } - [Fact] - public void IsTracePerformance() { - Assert.True(g.oracle.Ado.IsTracePerformance); - } - [Fact] public void ExecuteReader() { diff --git a/FreeSql.Tests/PostgreSQL/PostgreSQLAdo/PostgreSQLAdoTest.cs b/FreeSql.Tests/PostgreSQL/PostgreSQLAdo/PostgreSQLAdoTest.cs index 3877d781..73354609 100644 --- a/FreeSql.Tests/PostgreSQL/PostgreSQLAdo/PostgreSQLAdoTest.cs +++ b/FreeSql.Tests/PostgreSQL/PostgreSQLAdo/PostgreSQLAdoTest.cs @@ -14,11 +14,6 @@ namespace FreeSql.Tests.PostgreSQL { var t2 = g.pgsql.Ado.SlavePools.Count; } - [Fact] - public void IsTracePerformance() { - Assert.True(g.pgsql.Ado.IsTracePerformance); - } - [Fact] public void ExecuteReader() { diff --git a/FreeSql.Tests/SqlServer/SqlServerAdo/SqlServerAdoTest.cs b/FreeSql.Tests/SqlServer/SqlServerAdo/SqlServerAdoTest.cs index 4970d9be..67f9de1e 100644 --- a/FreeSql.Tests/SqlServer/SqlServerAdo/SqlServerAdoTest.cs +++ b/FreeSql.Tests/SqlServer/SqlServerAdo/SqlServerAdoTest.cs @@ -14,11 +14,6 @@ namespace FreeSql.Tests.SqlServer { var t2 = g.sqlserver.Ado.SlavePools.Count; } - [Fact] - public void IsTracePerformance() { - Assert.True(g.sqlserver.Ado.IsTracePerformance); - } - [Fact] public void ExecuteReader() { diff --git a/FreeSql.Tests/Sqlite/SqliteAdo/SqliteAdoTest.cs b/FreeSql.Tests/Sqlite/SqliteAdo/SqliteAdoTest.cs index 04d433f7..a847b45b 100644 --- a/FreeSql.Tests/Sqlite/SqliteAdo/SqliteAdoTest.cs +++ b/FreeSql.Tests/Sqlite/SqliteAdo/SqliteAdoTest.cs @@ -13,12 +13,6 @@ namespace FreeSql.Tests.Sqlite { public void SlavePools() { var t2 = g.sqlite.Ado.SlavePools.Count; } - - [Fact] - public void IsTracePerformance() { - Assert.True(g.sqlite.Ado.IsTracePerformance); - } - [Fact] public void ExecuteReader() { diff --git a/FreeSql.sln b/FreeSql.sln index e5f23de0..d0ddf954 100644 --- a/FreeSql.sln +++ b/FreeSql.sln @@ -25,6 +25,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{C6A74E2A-6 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xxx", "..\..\新建文件夹 (9)\xxx.csproj", "{6DC39740-0B26-4029-AB75-D436A7F666A2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Tests.PerformanceTests", "FreeSql.Tests.PerformanceTests\FreeSql.Tests.PerformanceTests.csproj", "{446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -71,6 +73,18 @@ Global {6DC39740-0B26-4029-AB75-D436A7F666A2}.Release|x64.Build.0 = Release|Any CPU {6DC39740-0B26-4029-AB75-D436A7F666A2}.Release|x86.ActiveCfg = Release|Any CPU {6DC39740-0B26-4029-AB75-D436A7F666A2}.Release|x86.Build.0 = Release|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Debug|x64.Build.0 = Debug|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Debug|x86.Build.0 = Debug|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Release|Any CPU.Build.0 = Release|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Release|x64.ActiveCfg = Release|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Release|x64.Build.0 = Release|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Release|x86.ActiveCfg = Release|Any CPU + {446D9CBE-BFE4-4FB3-ADFD-4C1C5EA1B6EE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index 7e9021c9..b31fbb27 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -2,10 +2,10 @@ netstandard2.0 - 0.0.5 + 0.0.6 true YeXiangQin - 打造 .NETCore 最方便的 ORM,DbFirst 与 CodeFirst 混合使用,提供从实体同步数据库,或者从数据库生成实体代码,支持 MySql/SqlServer/PostgreSQL 数据库。 + 打造 .NETCore 最方便的 ORM,DbFirst 与 CodeFirst 混合使用,提供从实体同步数据库,或者从数据库生成实体代码,支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite 数据库。 https://github.com/2881099/FreeSql FreeSql ORM @@ -24,6 +24,7 @@ + diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index 48c567b8..92bd8990 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -78,7 +78,7 @@ namespace FreeSql { /// 监视数据库命令对象 /// /// 执行前 - /// 执行后 + /// 执行后,可监视执行性能 /// public FreeSqlBuilder UseMonitorCommand(Action executing, Action executed = null) { _aopCommandExecuting = executing; diff --git a/FreeSql/Interface/IAdo.cs b/FreeSql/Interface/IAdo.cs index cee3ec4a..482fe438 100644 --- a/FreeSql/Interface/IAdo.cs +++ b/FreeSql/Interface/IAdo.cs @@ -18,9 +18,13 @@ namespace FreeSql { /// List> SlavePools { get; } /// - /// 是否跟踪记录SQL执行性能日志 + /// 监视数据库命令对象(执行前,调试) /// - bool IsTracePerformance { get; set; } + Action AopCommandExecuting { get; set; } + /// + /// 监视数据库命令对象(执行后,用于监视执行性能) + /// + Action AopCommandExecuted { get; set; } #region 事务 /// diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs index 39fe7a17..6ada413a 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Data; using System.Data.Common; +using System.Diagnostics; using System.Linq; using System.Text; @@ -13,10 +14,10 @@ namespace FreeSql.Internal.CommonProvider { protected abstract void ReturnConnection(ObjectPool pool, Object conn, Exception ex); protected abstract DbCommand CreateCommand(); protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj); - internal Action AopCommandExecuting = null; - internal Action AopCommandExecuted = null; + public Action AopCommandExecuting { get; set; } + public Action AopCommandExecuted { get; set; } - public bool IsTracePerformance { get; set; } = string.Compare(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Development", true) == 0; + protected bool IsTracePerformance => AopCommandExecuted != null; public ObjectPool MasterPool { get; protected set; } public List> SlavePools { get; } = new List>(); @@ -64,19 +65,15 @@ namespace FreeSql.Internal.CommonProvider { public List Query(string sql, object parms = null) => Query(CommandType.Text, sql, GetDbParamtersByObject(sql, parms)); public List Query(CommandType cmdType, string cmdText, params DbParameter[] cmdParms) { var names = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - var ds = new List(); + var ret = new List(); ExecuteReader(dr => { if (names.Any() == false) for (var a = 0; a < dr.FieldCount; a++) names.Add(dr.GetName(a), a); object[] values = new object[dr.FieldCount]; dr.GetValues(values); - ds.Add(values); + var read = Utils.ExecuteArrayRowReadClassOrTuple(typeof(T), names, values, 0); + ret.Add(read.value == null ? default(T) : (T)read.value); }, cmdType, cmdText, cmdParms); - var ret = new List(); - foreach (var row in ds) { - var read = Utils.ExecuteArrayRowReadClassOrTuple(typeof(T), names, row); - ret.Add(read.value == null ? default(T) : (T) read.value); - } return ret; } public void ExecuteReader(Action readerHander, string sql, object parms = null) => ExecuteReader(readerHander, CommandType.Text, sql, GetDbParamtersByObject(sql, parms)); diff --git a/FreeSql/Internal/Utils.cs b/FreeSql/Internal/Utils.cs index 4761ca30..4563295b 100644 --- a/FreeSql/Internal/Utils.cs +++ b/FreeSql/Internal/Utils.cs @@ -191,7 +191,7 @@ namespace FreeSql.Internal { dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写 var expandodic = (IDictionary)expando; foreach (var name in names) - expandodic[Utils.GetCsName(name.Key)] = row[name.Value]; + expandodic.Add(name.Key, row[name.Value]); return (expando, names.Count); } //类注入属性 diff --git a/readme.md b/readme.md index 171a5bc6..7b46e7cb 100644 --- a/readme.md +++ b/readme.md @@ -158,6 +158,33 @@ List t8 = fsql.Ado.Query("select * from song"); ``` > 更多资料:[《Select查询数据》](Docs/select.md) +## 性能测试 + +### FreeSql ToList & Dapper Query + +Elapsed: 00:00:00.9666720; Query Entity Counts: 131072; ORM: Dapper + +Elapsed: 00:00:01.4215325; ToList Entity Counts: 131072; ORM: FreeSql* + +### FreeSql Query & Dapper Query + +Elapsed: 00:00:00.9728656; Query Entity Counts: 131072; ORM: Dapper + +Elapsed: 00:00:00.4484073; Query Tuple Counts: 131072; ORM: Dapper + +Elapsed: 00:00:00.6580620; Query Dynamic Counts: 131072; ORM: Dapper + +Elapsed: 00:00:02.6804199; Query Entity Counts: 131072; ORM: FreeSql* + +Elapsed: 00:00:01.4161527; Query Tuple Counts: 131072; ORM: FreeSql* + +Elapsed: 00:00:00.9965082; Query Dynamic Counts: 131072; ORM: FreeSql* + +[查看测试代码](/2881099/FreeSql/tree/master/FreeSql.Tests.PerformanceTests/MySqlAdoTest.cs) + +FreeSql 目前使用的反射+缓存,比不过 Dapper Emit 性能。 + + # Part2 添加 ```csharp var items = new List();