├── .gitignore ├── LICENSE.txt ├── README.md └── Sources ├── DbUtility.sln ├── Ivony.Data.Logs ├── DbTraceService.cs ├── Ivony.Data.Logs.csproj ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Ivony.Data.MySql ├── Ivony.Data.MySql.csproj ├── MySqlClient │ ├── MySqlDbConfiguration.cs │ ├── MySqlDbExecutor.cs │ ├── MySqlDbTransactionContext.cs │ ├── MySqlExecuteContext.cs │ └── MySqlParameterizedQueryParser.cs ├── MySqlDb.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Ivony.Data.PostgreSQL ├── Ivony.Data.PostgreSQL.csproj ├── PostgreSql.cs ├── PostgreSqlClient │ ├── NpgsqlDbConfiguration.cs │ ├── NpgsqlDbExecutor.cs │ ├── NpgsqlDbTransactionContext.cs │ ├── NpgsqlExecuteContext.cs │ └── NpgsqlParameterizedQueryParser.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Ivony.Data.SQLite ├── Ivony.Data.SQLite.csproj ├── Properties │ └── AssemblyInfo.cs ├── SQLite.cs ├── SQLiteClient │ ├── SQLiteConfiguration.cs │ ├── SQLiteExecuteContext.cs │ ├── SQLiteExecutor.cs │ └── SQLiteParameterizedQueryParser.cs └── packages.config ├── Ivony.Data.Test ├── Ivony.Data.Test.csproj ├── MySqlTest.cs ├── ParameterizedQueryTest.cs ├── PostgreSqlTests.cs ├── Properties │ └── AssemblyInfo.cs ├── SQLiteTest.cs ├── SqlServerTest.cs ├── TestTraceService.cs ├── packages.config ├── x64 │ └── SQLite.Interop.dll └── x86 │ └── SQLite.Interop.dll ├── Ivony.Data ├── BasicExecuteExtensions.cs ├── Common │ ├── DataTableAdapter.cs │ ├── DbExecuteContextBase.cs │ ├── DbExecutorBase.cs │ ├── DbTransactionContextBase.cs │ ├── IDbProvider.cs │ ├── IParameterizedQueryParser.cs │ ├── ParameterizedQueryLiteralValueParser.cs │ ├── ParameterizedQueryParser.cs │ └── XmlDocumentValueConverter.cs ├── DataSetExtensions.cs ├── Db.cs ├── DbConfiguration.cs ├── DbExecutableQuery.cs ├── DbTracing.cs ├── DbValueConverter.cs ├── DefaultConverter.cs ├── DynamicExtensions.cs ├── EntityConvert.cs ├── EntityConvertAttribute.cs ├── EntityExtensions.cs ├── IDbExecutableQuery.cs ├── IDbExecuteContext.cs ├── IDbExecutor.cs ├── IDbQuery.cs ├── IDbTraceService.cs ├── IDbTracing.cs ├── IDbTransactionContext.cs ├── IDbTransactionProvider.cs ├── IDbValueConverter.cs ├── Ivony.Data.csproj ├── Properties │ └── AssemblyInfo.cs ├── Queries │ ├── IParameterizedQueryPartial.cs │ ├── ParameterArray.cs │ ├── ParameterizedQuery.cs │ ├── ParameterizedQueryBuilder.cs │ ├── StoredProcedureQuery.cs │ └── TemplateParser.cs ├── SqlClient │ ├── SqlDbConfiguration.cs │ ├── SqlDbExecuteContext.cs │ ├── SqlDbExecutor.cs │ ├── SqlDbTransactionContext.cs │ └── SqlParameterizedQueryParser.cs ├── SqlServer.cs ├── SqlServerExpress.cs ├── SqlServerHelper.cs ├── TemplateExtensions.cs ├── TransactionExtensions.cs └── packages.config ├── PerformanceTest ├── App.config ├── PerformanceTest.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── UpgradeLog.htm └── packages ├── Ivony.Core.1.0.0 ├── Ivony.Core.1.0.0.nupkg ├── Ivony.Core.1.0.0.nuspec └── lib │ ├── Ivony.Core.dll │ └── Ivony.Core.xml ├── Ivony.Logs.1.2 ├── Ivony.Logs.1.2.nupkg └── lib │ └── net40 │ └── Ivony.Logs.dll ├── MySql.Data.6.8.3 ├── MySql.Data.6.8.3.nupkg └── lib │ ├── net20-cf │ └── MySql.Data.cf.dll │ ├── net20 │ └── MySql.Data.dll │ ├── net40 │ └── MySql.Data.dll │ ├── net45 │ └── MySql.Data.dll │ └── netcore45 │ └── MySql.Data.RT.dll ├── Npgsql.2.1.3 ├── Npgsql.2.1.3.nupkg └── lib │ ├── net20 │ ├── Mono.Security.dll │ ├── Npgsql.dll │ ├── Npgsql.xml │ ├── de │ │ └── Npgsql.resources.dll │ ├── es │ │ └── Npgsql.resources.dll │ ├── fi │ │ └── Npgsql.resources.dll │ ├── fr │ │ └── Npgsql.resources.dll │ ├── ja │ │ └── Npgsql.resources.dll │ └── zh-CN │ │ └── Npgsql.resources.dll │ ├── net35 │ ├── Mono.Security.dll │ ├── Npgsql.dll │ ├── Npgsql.xml │ ├── de │ │ └── Npgsql.resources.dll │ ├── es │ │ └── Npgsql.resources.dll │ ├── fi │ │ └── Npgsql.resources.dll │ ├── fr │ │ └── Npgsql.resources.dll │ ├── ja │ │ └── Npgsql.resources.dll │ └── zh-CN │ │ └── Npgsql.resources.dll │ ├── net40 │ ├── Mono.Security.dll │ ├── Npgsql.dll │ ├── Npgsql.xml │ ├── de │ │ └── Npgsql.resources.dll │ ├── es │ │ └── Npgsql.resources.dll │ ├── fi │ │ └── Npgsql.resources.dll │ ├── fr │ │ └── Npgsql.resources.dll │ ├── ja │ │ └── Npgsql.resources.dll │ └── zh-CN │ │ └── Npgsql.resources.dll │ └── net45 │ ├── Mono.Security.dll │ ├── Npgsql.dll │ ├── Npgsql.xml │ ├── de │ └── Npgsql.resources.dll │ ├── es │ └── Npgsql.resources.dll │ ├── fi │ └── Npgsql.resources.dll │ ├── fr │ └── Npgsql.resources.dll │ ├── ja │ └── Npgsql.resources.dll │ └── zh-CN │ └── Npgsql.resources.dll ├── System.Data.SQLite.Core.1.0.92.0 ├── System.Data.SQLite.Core.1.0.92.0.nupkg ├── content │ ├── net20 │ │ ├── x64 │ │ │ └── SQLite.Interop.dll │ │ └── x86 │ │ │ └── SQLite.Interop.dll │ ├── net40 │ │ ├── x64 │ │ │ └── SQLite.Interop.dll │ │ └── x86 │ │ │ └── SQLite.Interop.dll │ ├── net45 │ │ ├── x64 │ │ │ └── SQLite.Interop.dll │ │ └── x86 │ │ │ └── SQLite.Interop.dll │ └── net451 │ │ ├── x64 │ │ └── SQLite.Interop.dll │ │ └── x86 │ │ └── SQLite.Interop.dll ├── lib │ ├── net20 │ │ ├── System.Data.SQLite.dll │ │ └── System.Data.SQLite.xml │ ├── net40 │ │ ├── System.Data.SQLite.dll │ │ └── System.Data.SQLite.xml │ ├── net45 │ │ ├── System.Data.SQLite.dll │ │ └── System.Data.SQLite.xml │ └── net451 │ │ ├── System.Data.SQLite.dll │ │ └── System.Data.SQLite.xml └── tools │ ├── net20 │ └── install.ps1 │ ├── net40 │ └── install.ps1 │ ├── net45 │ └── install.ps1 │ └── net451 │ └── install.ps1 ├── System.Data.SQLite.Core.MSIL.1.0.92.0 ├── System.Data.SQLite.Core.MSIL.1.0.92.0.nupkg └── lib │ ├── net20 │ ├── System.Data.SQLite.dll │ └── System.Data.SQLite.xml │ ├── net40 │ ├── System.Data.SQLite.dll │ └── System.Data.SQLite.xml │ ├── net45 │ ├── System.Data.SQLite.dll │ └── System.Data.SQLite.xml │ └── net451 │ ├── System.Data.SQLite.dll │ └── System.Data.SQLite.xml └── repositories.config /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Visual Studio 3 | ################# 4 | 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.sln.docstates 12 | .vs 13 | 14 | # Build results 15 | [Dd]ebug/ 16 | [Rr]elease/ 17 | *_i.c 18 | *_p.c 19 | *.ilk 20 | *.meta 21 | *.obj 22 | *.pch 23 | *.pdb 24 | *.pgc 25 | *.pgd 26 | *.rsp 27 | *.sbr 28 | *.tlb 29 | *.tli 30 | *.tlh 31 | *.tmp 32 | *.vspscc 33 | .builds 34 | *.dotCover 35 | 36 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 37 | #packages/ 38 | 39 | # Visual C++ cache files 40 | ipch/ 41 | *.aps 42 | *.ncb 43 | *.opensdf 44 | *.sdf 45 | 46 | # Visual Studio profiler 47 | *.psess 48 | *.vsp 49 | 50 | # ReSharper is a .NET coding add-in 51 | _ReSharper* 52 | 53 | # Installshield output folder 54 | [Ee]xpress 55 | 56 | # DocProject is a documentation generator add-in 57 | DocProject/buildhelp/ 58 | DocProject/Help/*.HxT 59 | DocProject/Help/*.HxC 60 | DocProject/Help/*.hhc 61 | DocProject/Help/*.hhk 62 | DocProject/Help/*.hhp 63 | DocProject/Help/Html2 64 | DocProject/Help/html 65 | 66 | # Click-Once directory 67 | publish 68 | 69 | # Others 70 | [Bb]in 71 | [Oo]bj 72 | sql 73 | TestResults 74 | *.Cache 75 | ClientBin 76 | stylecop.* 77 | ~$* 78 | *.dbmdl 79 | Generated_Code #added for RIA/Silverlight projects 80 | 81 | # Backup & report files from converting an old project file to a newer 82 | # Visual Studio version. Backup files are not needed, because we have git ;-) 83 | _UpgradeReport_Files/ 84 | Backup*/ 85 | UpgradeLog*.XML 86 | 87 | 88 | 89 | ############ 90 | ## Windows 91 | ############ 92 | 93 | # Windows image file caches 94 | Thumbs.db 95 | 96 | # Folder config file 97 | Desktop.ini 98 | 99 | .localhistory 100 | /.vs 101 | /.vs 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DataPithy 2 | ========= 3 | 4 | 5 | 6 | DataPithy is a light database access tool 7 | 8 | 9 | ## How to use 10 | 11 | execute a query 12 | ```CSharp 13 | db.T( "SELECT * FROM Members" ).ExecuteDataTable(); 14 | ``` 15 | 16 | execute a query with parameter and return first row 17 | ```CSharp 18 | db.T( "SELECT FirstName, LastName FROM Members WHERE Username = {0}", username ).ExecuteFirstRow(); 19 | ``` 20 | 21 | execute a query as async. 22 | ```CSharp 23 | await db.T( "SELECT FirstName, LastName FROM Members WHERE Username = {0}", username ).ExecuteFirstRowAsync(); 24 | ``` 25 | 26 | ## Basic concept 27 | 28 | ```CSharp 29 | db.T( "SELECT FirstName, LastName FROM Members WHERE Username = {0}", username ).ExecuteFirstRow(); 30 | ``` 31 | 32 | In the code above, 33 | ```db``` is called **database executor**,
34 | ```T( "SELECT FirstName, LastName FROM Members WHERE Username = {0}", username )``` is called **query definition**,
35 | and ```ExecuteFirstRow()``` is called **result definition**
36 | 37 | --- 38 | 39 | The following code creates a **database executor** 40 | ```CSharp 41 | var db = SqlServer.Create( "connection-string-name" ); 42 | ``` 43 | Or 44 | ```CSharp 45 | var db = SqlServer.Connect( "connection-string" ); 46 | ``` 47 | 48 | **database executor** is responsible for createing connection and executing queries. 49 | 50 | ---- 51 | 52 | A typical **query definition** like this below 53 | ```CSharp 54 | db.T( "query-text-template", params parameters ); 55 | ``` 56 | The query text is SQL command to be executed. and you can use parameter placehold inside like ```string.Format``` syntax. like this below: 57 | ```CSharp 58 | db.T( "SELECT MemberID FROM Members WHERE Username = {0} AND Password = {1}", username, password ) 59 | ``` 60 | it will create a SQL query like this below: 61 | ```SQL 62 | DECLARE @Param0 AS nvarchar = 'text of username'; 63 | DECLARE @Param1 AS nvarchar = 'text of password'; 64 | SELECT MemberID FROM Members WHERE Username = @Param0 AND Password = @Param1; 65 | ``` 66 | the method name **T** means **Template**, so we can also write code like below: 67 | ```CSharp 68 | db.Template( "SELECT MemberID FROM Members WHERE Username = {0} AND Password = {1}", username, password ) 69 | ``` 70 | and the **T** is an **extension method**, you can declare another query definition method **as you like**. 71 | 72 | --- 73 | 74 | In the last, we talk about the **result definition**. 75 | like same as the query definition, result definition are also en extension method. we have many result definition method, and all of they have asynchronous version. 76 | the popular result definition method under this: 77 | 78 | **ExecuteNonQuery**, execute query, and return the number of rows affected.
79 | **ExecuteScaler**, execute query and return the first column of the first row.
80 | **ExecuteDataTable**, execute query and fill a DataTable and return.
81 | **ExecuteFirstRow**, execute query and return ths first row.
82 | **ExecuteEntity**, execute query and return the first row to fill the specified type of entity 83 | 84 | ## Get It 85 | 86 | you can download last stable release from nuget: 87 | [DataPithy](http://www.nuget.org/packages/DbWrench/) 88 | -------------------------------------------------------------------------------- /Sources/DbUtility.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ivony.Data", "Ivony.Data\Ivony.Data.csproj", "{27D46D02-F7BC-42B2-AE3E-33EB5B1FA3F9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ivony.Data.Test", "Ivony.Data.Test\Ivony.Data.Test.csproj", "{D86B5F37-0FB4-4E69-8A00-E4F93B5C6EC6}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ivony.Data.MySql", "Ivony.Data.MySql\Ivony.Data.MySql.csproj", "{297C6A4C-086B-426D-B146-DF352410DCF0}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ivony.Data.SQLite", "Ivony.Data.SQLite\Ivony.Data.SQLite.csproj", "{7388FD8C-4D38-457F-A5D0-0C006ABBF15B}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ivony.Data.PostgreSQL", "Ivony.Data.PostgreSQL\Ivony.Data.PostgreSQL.csproj", "{AD094A3A-E91F-4810-AE70-1E2B038CD98E}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ivony.Data.Logs", "Ivony.Data.Logs\Ivony.Data.Logs.csproj", "{F0FB655F-B8A5-4CEB-8A66-C9BF12399956}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerformanceTest", "PerformanceTest\PerformanceTest.csproj", "{EF894E7A-779D-483C-89F1-61541833DD34}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {27D46D02-F7BC-42B2-AE3E-33EB5B1FA3F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {27D46D02-F7BC-42B2-AE3E-33EB5B1FA3F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {27D46D02-F7BC-42B2-AE3E-33EB5B1FA3F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {27D46D02-F7BC-42B2-AE3E-33EB5B1FA3F9}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {D86B5F37-0FB4-4E69-8A00-E4F93B5C6EC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {D86B5F37-0FB4-4E69-8A00-E4F93B5C6EC6}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {D86B5F37-0FB4-4E69-8A00-E4F93B5C6EC6}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {D86B5F37-0FB4-4E69-8A00-E4F93B5C6EC6}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {297C6A4C-086B-426D-B146-DF352410DCF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {297C6A4C-086B-426D-B146-DF352410DCF0}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {297C6A4C-086B-426D-B146-DF352410DCF0}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {297C6A4C-086B-426D-B146-DF352410DCF0}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {7388FD8C-4D38-457F-A5D0-0C006ABBF15B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {7388FD8C-4D38-457F-A5D0-0C006ABBF15B}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {7388FD8C-4D38-457F-A5D0-0C006ABBF15B}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {7388FD8C-4D38-457F-A5D0-0C006ABBF15B}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {AD094A3A-E91F-4810-AE70-1E2B038CD98E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {AD094A3A-E91F-4810-AE70-1E2B038CD98E}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {AD094A3A-E91F-4810-AE70-1E2B038CD98E}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {AD094A3A-E91F-4810-AE70-1E2B038CD98E}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {F0FB655F-B8A5-4CEB-8A66-C9BF12399956}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {F0FB655F-B8A5-4CEB-8A66-C9BF12399956}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {F0FB655F-B8A5-4CEB-8A66-C9BF12399956}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {F0FB655F-B8A5-4CEB-8A66-C9BF12399956}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {EF894E7A-779D-483C-89F1-61541833DD34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {EF894E7A-779D-483C-89F1-61541833DD34}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {EF894E7A-779D-483C-89F1-61541833DD34}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {EF894E7A-779D-483C-89F1-61541833DD34}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Logs/DbTraceService.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Logs; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data.Logs 10 | { 11 | public class DbTraceService : IDbTraceService 12 | { 13 | 14 | public DbTraceService( Logger logger ) 15 | { 16 | 17 | Logger = logger; 18 | 19 | } 20 | 21 | protected Logger Logger 22 | { 23 | get; 24 | private set; 25 | } 26 | 27 | 28 | 29 | 30 | 31 | public IDbTracing CreateTracing( IDbExecutor executor, TQuery query ) where TQuery : IDbQuery 32 | { 33 | return new DbTracing( query, LogTracing ); 34 | } 35 | 36 | protected virtual void LogTracing( DbTracing tracing ) 37 | { 38 | Logger.LogEntry( CreateEntry( tracing ) ); 39 | } 40 | 41 | protected LogEntry CreateEntry( DbTracing tracing ) 42 | { 43 | if ( tracing.Exception != null ) 44 | { 45 | 46 | using ( var writer = new StringWriter() ) 47 | { 48 | 49 | writer.WriteLine( "执行数据查询时出现异常" ); 50 | writer.WriteLine( "执行的查询:" ); 51 | writer.WriteLine( tracing.QueryObject ); 52 | writer.WriteLine( new string( '-', 30 ) ); 53 | if ( tracing.CommandObject != null ) 54 | { 55 | writer.WriteLine( "命令对象:" ); 56 | writer.WriteLine( tracing.CommandObject ); 57 | writer.WriteLine( new string( '-', 30 ) ); 58 | } 59 | 60 | writer.WriteLine( "查询花费时间: {0}", tracing.QueryTime ); 61 | writer.WriteLine( "异常详细信息:" ); 62 | writer.WriteLine( tracing.Exception ); 63 | writer.WriteLine( new string( '=', 30 ) ); 64 | 65 | return new LogEntry( writer.ToString(), new LogMeta() { Type = LogType.Exception } ); 66 | } 67 | } 68 | else 69 | { 70 | using ( var writer = new StringWriter() ) 71 | { 72 | 73 | writer.WriteLine( "成功执行查询" ); 74 | 75 | writer.WriteLine( "执行的查询:" ); 76 | writer.WriteLine( tracing.QueryObject ); 77 | writer.WriteLine( new string( '-', 30 ) ); 78 | 79 | writer.WriteLine( "命令对象:" ); 80 | writer.WriteLine( tracing.CommandObject ); 81 | writer.WriteLine( new string( '-', 30 ) ); 82 | 83 | 84 | writer.WriteLine( "数据库执行时间: {0}", tracing.ExecutionTime ); 85 | writer.WriteLine( "查询总计花费: {0}", tracing.QueryTime ); 86 | writer.WriteLine( new string( '=', 30 ) ); 87 | 88 | return new LogEntry( writer.ToString(), new LogMeta() { Type = LogType.Info } ); 89 | } 90 | } 91 | } 92 | 93 | 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Logs/Ivony.Data.Logs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F0FB655F-B8A5-4CEB-8A66-C9BF12399956} 8 | Library 9 | Properties 10 | Ivony.Data.Logs 11 | Ivony.Data.Logs 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\Ivony.Logs.1.2\lib\net40\Ivony.Logs.dll 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {27d46d02-f7bc-42b2-ae3e-33eb5b1fa3f9} 55 | Ivony.Data 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Logs/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Ivony.Data.Logs")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Ivony.Data.Logs")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("2095d09c-6001-43e2-9fbb-5252bf3cff99")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Logs/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/Ivony.Data.MySql.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {297C6A4C-086B-426D-B146-DF352410DCF0} 8 | Library 9 | Properties 10 | Ivony.Data 11 | DbWrench.MySql 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\MySql.Data.6.8.3\lib\net45\MySql.Data.dll 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {27d46d02-f7bc-42b2-ae3e-33eb5b1fa3f9} 61 | Ivony.Data 62 | 63 | 64 | 65 | 72 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/MySqlClient/MySqlDbConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MySql.Data.MySqlClient; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data.MySqlClient 9 | { 10 | public class MySqlDbConfiguration : DbConfiguration 11 | { 12 | 13 | public MySqlDbConfiguration() { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/MySqlClient/MySqlDbExecutor.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Ivony.Data.Queries; 3 | using MySql.Data.MySqlClient; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Data.Common; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | 12 | 13 | namespace Ivony.Data.MySqlClient 14 | { 15 | /// 16 | /// 用于操作 MySQL 的数据库访问工具 17 | /// 18 | public class MySqlDbExecutor : DbExecutorBase, IDbExecutor, IDbTransactionProvider 19 | { 20 | 21 | 22 | 23 | public MySqlDbExecutor( string connectionString, MySqlDbConfiguration configuration ) 24 | : base( configuration ) 25 | { 26 | 27 | if ( connectionString == null ) 28 | throw new ArgumentNullException( "connectionString" ); 29 | 30 | if ( configuration == null ) 31 | throw new ArgumentNullException( "configuration" ); 32 | 33 | ConnectionString = connectionString; 34 | Configuration = configuration; 35 | 36 | } 37 | 38 | 39 | protected string ConnectionString 40 | { 41 | get; 42 | private set; 43 | } 44 | 45 | 46 | 47 | protected MySqlDbConfiguration Configuration 48 | { 49 | get; 50 | private set; 51 | } 52 | 53 | public IDbExecuteContext Execute( ParameterizedQuery query ) 54 | { 55 | 56 | return Execute( CreateCommand( query ), TryCreateTracing( this, query ) ); 57 | 58 | } 59 | 60 | protected virtual IDbExecuteContext Execute( MySqlCommand command, IDbTracing tracing ) 61 | { 62 | try 63 | { 64 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 65 | 66 | 67 | var connection = new MySqlConnection( ConnectionString ); 68 | connection.Open(); 69 | command.Connection = connection; 70 | 71 | if ( Configuration.QueryExecutingTimeout.HasValue ) 72 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 73 | 74 | var context = new MySqlExecuteContext( connection, command.ExecuteReader(), tracing ); 75 | 76 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 77 | 78 | return context; 79 | } 80 | catch ( DbException exception ) 81 | { 82 | TryExecuteTracing( tracing, t => t.OnException( exception ) ); 83 | throw; 84 | } 85 | } 86 | 87 | 88 | 89 | private MySqlCommand CreateCommand( ParameterizedQuery query ) 90 | { 91 | 92 | return new MySqlParameterizedQueryParser().Parse( query ); 93 | } 94 | 95 | 96 | IDbTransactionContext IDbTransactionProvider.CreateTransaction() 97 | { 98 | return new MySqlDbTransactionContext( ConnectionString, Configuration ); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/MySqlClient/MySqlDbTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using MySql.Data.MySqlClient; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data.MySqlClient 11 | { 12 | public class MySqlDbTransactionContext : DbTransactionContextBase 13 | { 14 | 15 | 16 | 17 | 18 | /// 19 | /// 获取数据库连接 20 | /// 21 | public MySqlConnection Connection 22 | { 23 | get; 24 | private set; 25 | } 26 | 27 | 28 | 29 | internal MySqlDbTransactionContext( string connectionString, MySqlDbConfiguration configuration ) 30 | { 31 | Connection = new MySqlConnection( connectionString ); 32 | _executor = new MySqlDbExecutorWithTransaction( this, configuration ); 33 | } 34 | 35 | 36 | 37 | /// 38 | /// 打开数据库连接并创建数据库事务对象。 39 | /// 40 | /// SQL Server 数据库事务对象 41 | protected override MySqlTransaction CreateTransaction() 42 | { 43 | if ( Connection.State == ConnectionState.Closed ) 44 | Connection.Open(); 45 | 46 | return Connection.BeginTransaction(); 47 | } 48 | 49 | 50 | 51 | private MySqlDbExecutor _executor; 52 | 53 | /// 54 | /// 获取用于在事务中执行查询的 MySql 查询执行器 55 | /// 56 | public override MySqlDbExecutor DbExecutor 57 | { 58 | get { return _executor; } 59 | } 60 | 61 | 62 | private class MySqlDbExecutorWithTransaction : MySqlDbExecutor 63 | { 64 | 65 | public MySqlDbExecutorWithTransaction( MySqlDbTransactionContext transaction, MySqlDbConfiguration configuration ) 66 | : base( transaction.Connection.ConnectionString, configuration ) 67 | { 68 | _transaction = transaction; 69 | } 70 | 71 | 72 | private MySqlDbTransactionContext _transaction; 73 | 74 | 75 | protected override IDbExecuteContext Execute( MySqlCommand command, IDbTracing tracing ) 76 | { 77 | 78 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 79 | 80 | command.Connection = _transaction.Connection; 81 | command.Transaction = _transaction.Transaction; 82 | 83 | if ( Configuration.QueryExecutingTimeout.HasValue ) 84 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 85 | 86 | 87 | var dataReader = command.ExecuteReader(); 88 | var context = new MySqlExecuteContext( _transaction, dataReader, tracing ); 89 | 90 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 91 | 92 | return context; 93 | } 94 | 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/MySqlClient/MySqlExecuteContext.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using MySql.Data.MySqlClient; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace Ivony.Data.MySqlClient 10 | { 11 | 12 | /// 13 | /// MySql 数据执行上下文 14 | /// 15 | public class MySqlExecuteContext : AsyncDbExecuteContextBase 16 | { 17 | 18 | /// 19 | /// 创建 MySqlExecuteContext 对象 20 | /// 21 | /// MySql 数据库连接 22 | /// MySql 数据读取器 23 | /// 用于当前查询的追踪器 24 | public MySqlExecuteContext( MySqlConnection connection, MySqlDataReader dataReader, IDbTracing tracing ) 25 | : base( dataReader, tracing, connection ) 26 | { 27 | MySqlDataReader = dataReader; 28 | } 29 | 30 | /// 31 | /// 创建 MySqlExecuteContext 对象 32 | /// 33 | /// MySql 数据库事务上下文 34 | /// MySql 数据读取器 35 | /// 用于当前查询的追踪器 36 | public MySqlExecuteContext( MySqlDbTransactionContext transaction, MySqlDataReader dataReader, IDbTracing tracing ) 37 | : base( dataReader, tracing, null ) 38 | { 39 | TransactionContext = transaction; 40 | MySqlDataReader = dataReader; 41 | } 42 | 43 | 44 | /// 45 | /// 数据读取器 46 | /// 47 | public MySqlDataReader MySqlDataReader 48 | { 49 | get; 50 | private set; 51 | } 52 | 53 | 54 | /// 55 | /// 数据库事务上下文,如果有的话 56 | /// 57 | public MySqlDbTransactionContext TransactionContext 58 | { 59 | get; 60 | private set; 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/MySqlClient/MySqlParameterizedQueryParser.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Ivony.Data.Queries; 3 | using MySql.Data.MySqlClient; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data.MySqlClient 11 | { 12 | public class MySqlParameterizedQueryParser : ParameterizedQueryParser 13 | { 14 | protected override string GetParameterPlaceholder( object value, int index, out MySqlParameter parameter ) 15 | { 16 | var name = "?Param" + index; 17 | parameter = new MySqlParameter( name, value ); 18 | 19 | return name; 20 | } 21 | 22 | protected override MySqlCommand CreateCommand( string commandText, MySqlParameter[] parameters ) 23 | { 24 | var command = new MySqlCommand( commandText ); 25 | command.Parameters.AddRange( parameters ); 26 | 27 | return command; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/MySqlDb.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Ivony.Data.MySqlClient; 3 | using Ivony.Data.SqlClient; 4 | using MySql.Data.MySqlClient; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Configuration; 8 | using System.Data.SqlClient; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace Ivony.Data 14 | { 15 | 16 | /// 17 | /// 提供 MySql 数据库支持 18 | /// 19 | public static class MySqlDb 20 | { 21 | 22 | /// 23 | /// 从配置文件中读取连接字符串并创建 MySql 数据库访问器 24 | /// 25 | /// 连接字符串配置名称 26 | /// MySql 配置 27 | /// MySql 数据库访问器 28 | public static MySqlDbExecutor FromConfiguration( string name, MySqlDbConfiguration configuration = null ) 29 | { 30 | var setting = ConfigurationManager.ConnectionStrings[name]; 31 | if ( setting == null ) 32 | throw new InvalidOperationException(); 33 | 34 | return Connect( setting.ConnectionString, configuration ); 35 | } 36 | 37 | 38 | /// 39 | /// 通过指定的连接字符串并创建 MySql 数据库访问器 40 | /// 41 | /// 连接字符串 42 | /// MySql 配置 43 | /// MySql 数据库访问器 44 | public static MySqlDbExecutor Connect( string connectionString, MySqlDbConfiguration configuration = null ) 45 | { 46 | return new MySqlDbExecutor( connectionString, configuration ?? DefaultConfiguration ); 47 | } 48 | 49 | 50 | 51 | /// 52 | /// 通过指定的连接字符串构建器创建 MySql 数据库访问器 53 | /// 54 | /// 连接字符串构建器 55 | /// MySql 配置 56 | /// MySql 数据库访问器 57 | public static MySqlDbExecutor Connect( MySqlConnectionStringBuilder builder, MySqlDbConfiguration configuration = null ) 58 | { 59 | return Connect( builder.ConnectionString, configuration ); 60 | } 61 | 62 | 63 | 64 | /// 65 | /// 通过指定的用户名和密码登陆 MySql 数据库,以创建 MySql 数据库访问器 66 | /// 67 | /// 数据库服务器地址 68 | /// 数据库名称 69 | /// 登录数据库的用户名 70 | /// 登录数据库的密码 71 | /// 是否启用连接池(默认启用) 72 | /// MySql 数据库配置 73 | /// MySql 数据库访问器 74 | public static MySqlDbExecutor Connect( string server, string database, string userID, string password, bool pooling = true, MySqlDbConfiguration configuration = null ) 75 | { 76 | var builder = new MySqlConnectionStringBuilder() 77 | { 78 | Server = server, 79 | Database = database, 80 | IntegratedSecurity = false, 81 | UserID = userID, 82 | Password = password, 83 | Pooling = pooling 84 | }; 85 | 86 | return Connect( builder.ConnectionString, configuration ); 87 | } 88 | 89 | 90 | /// 91 | /// 通过指定的用户名和密码登陆 MySql 数据库,以创建 MySql 数据库访问器 92 | /// 93 | /// 数据库服务器地址 94 | /// 数据库服务器端口 95 | /// 数据库名称 96 | /// 登录数据库的用户名 97 | /// 登录数据库的密码 98 | /// 是否启用连接池(默认启用) 99 | /// MySql 数据库配置 100 | /// MySql 数据库访问器 101 | public static MySqlDbExecutor Connect( string server, uint port, string database, string userID, string password, bool pooling = true, MySqlDbConfiguration configuration = null ) 102 | { 103 | var builder = new MySqlConnectionStringBuilder() 104 | { 105 | Server = server, 106 | Database = database, 107 | IntegratedSecurity = false, 108 | UserID = userID, 109 | Password = password, 110 | Pooling = pooling 111 | }; 112 | 113 | return Connect( builder.ConnectionString, configuration ); 114 | } 115 | 116 | 117 | /// 118 | /// 通过集成身份验证登陆 MySql 数据库,以创建 MySql 数据库访问器 119 | /// 120 | /// 数据库服务器实例名称 121 | /// 数据库名称 122 | /// 是否启用连接池(默认启用) 123 | /// MySql 数据库配置 124 | /// MySql 数据库访问器 125 | public static MySqlDbExecutor Connect( string server, string database, bool pooling = true, MySqlDbConfiguration configuration = null ) 126 | { 127 | 128 | var builder = new MySqlConnectionStringBuilder() 129 | { 130 | Server = server, 131 | Database = database, 132 | IntegratedSecurity = true, 133 | Pooling = pooling 134 | }; 135 | 136 | return Connect( builder.ConnectionString, configuration ); 137 | } 138 | 139 | 140 | 141 | 142 | /// 143 | /// 通过集成身份验证登陆 MySql 数据库,以创建 MySql 数据库访问器 144 | /// 145 | /// 数据库服务器地址 146 | /// 数据库服务器端口 147 | /// 数据库名称 148 | /// 是否启用连接池(默认启用) 149 | /// MySql 数据库配置 150 | /// MySql 数据库访问器 151 | public static MySqlDbExecutor Connect( string server, uint port, string database, bool pooling = true, MySqlDbConfiguration configuration = null ) 152 | { 153 | 154 | var builder = new MySqlConnectionStringBuilder() 155 | { 156 | Server = server, 157 | Port = port, 158 | Database = database, 159 | IntegratedSecurity = true, 160 | Pooling = pooling 161 | }; 162 | 163 | return Connect( builder.ConnectionString, configuration ); 164 | } 165 | 166 | 167 | 168 | 169 | 170 | static MySqlDb() 171 | { 172 | DefaultConfiguration = new MySqlDbConfiguration(); 173 | } 174 | 175 | 176 | /// 177 | /// 获取或设置默认配置 178 | /// 179 | public static MySqlDbConfiguration DefaultConfiguration 180 | { 181 | get; 182 | set; 183 | } 184 | 185 | 186 | /// 187 | /// 获取或设置 MySql 全局设置 188 | /// 189 | public static MySqlConfiguration MySqlGlobalSettings 190 | { 191 | get { return MySqlConfiguration.Settings; } 192 | } 193 | 194 | 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle( "DbWrench MySQL Provider" )] 9 | [assembly: AssemblyDescription( "DbWrench MySQL Provider" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "DbWrench MySQL" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2009 Ivony Licensed under the Apache License, Version 2.0" )] 14 | [assembly: AssemblyTrademark( "DbWrench" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible( false )] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid( "a539c3b3-6d5f-4e11-8997-2d62e246b620" )] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | [assembly: AssemblyVersion( "1.0.*" )] 33 | [assembly: AssemblyFileVersion( "1.0" )] 34 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.MySql/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/Ivony.Data.PostgreSQL.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {AD094A3A-E91F-4810-AE70-1E2B038CD98E} 8 | Library 9 | Properties 10 | Ivony.Data.PostgreSQL 11 | Ivony.Data.PostgreSQL 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | False 36 | ..\packages\Ivony.Core.1.0.0\lib\Ivony.Core.dll 37 | 38 | 39 | ..\packages\Npgsql.2.1.3\lib\net45\Mono.Security.dll 40 | 41 | 42 | ..\packages\Npgsql.2.1.3\lib\net45\Npgsql.dll 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | {27d46d02-f7bc-42b2-ae3e-33eb5b1fa3f9} 68 | Ivony.Data 69 | 70 | 71 | 72 | 79 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/PostgreSql.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using Ivony.Data.PostgreSQL.PostgreSqlClient; 4 | using Npgsql; 5 | 6 | namespace Ivony.Data.PostgreSQL 7 | { 8 | /// 9 | /// 提供 PostgreSQL 数据库访问支持 10 | /// 11 | public static class PostgreSql 12 | { 13 | /// 14 | /// 从配置文件中读取连接字符串并创建 PostgreSQL 数据库访问器 15 | /// 16 | /// 连接字符串配置名称 17 | /// PostgreSQL 配置 18 | /// PostgreSQL 数据库访问器 19 | public static NpgsqlDbExecutor FromConfiguration( string name, NpgsqlDbConfiguration configuration = null ) 20 | { 21 | var setting = ConfigurationManager.ConnectionStrings[name]; 22 | if ( setting == null ) 23 | throw new InvalidOperationException(); 24 | 25 | return Connect( setting.ConnectionString, configuration ); 26 | } 27 | 28 | /// 29 | /// 通过指定的连接字符串并创建 PostgreSQL 数据库访问器 30 | /// 31 | /// 连接字符串 32 | /// PostgreSQL配置 33 | /// PostgreSQL 数据库访问器 34 | public static NpgsqlDbExecutor Connect( string connectionString, NpgsqlDbConfiguration configuration = null ) 35 | { 36 | return new NpgsqlDbExecutor( connectionString, configuration ?? DefaultConfiguration ); 37 | } 38 | 39 | /// 40 | /// 通过指定的连接字符串构建器创建 PostgreSQL 数据库访问器 41 | /// 42 | /// 连接字符串构建器 43 | /// PostgreSQL配置 44 | /// PostgreSQL 数据库访问器 45 | public static NpgsqlDbExecutor Connect( NpgsqlConnectionStringBuilder builder, NpgsqlDbConfiguration configuration = null ) 46 | { 47 | return Connect( builder.ConnectionString, configuration ); 48 | } 49 | 50 | /// 51 | /// 通过指定的用户名和密码登陆 PostgreSQL 数据库,以创建 PostgreSQL 数据库访问器 52 | /// 53 | /// 数据库服务器实例名称 54 | /// 数据库名称 55 | /// 数据库端口 56 | /// 登录数据库的用户名 57 | /// 登录数据库的密码 58 | /// 是否启用连接池(默认启用) 59 | /// PostgreSQL数据库配置 60 | /// PostgreSQL 数据库访问器 61 | public static NpgsqlDbExecutor Connect( string host, string database, int port, string userID, string password, bool pooling = true, NpgsqlDbConfiguration configuration = null ) 62 | { 63 | var builder = new NpgsqlConnectionStringBuilder 64 | { 65 | Host = host, 66 | Database = database, 67 | Port = port, 68 | IntegratedSecurity = false, 69 | UserName = userID, 70 | Password = password, 71 | Pooling = pooling 72 | }; 73 | 74 | return Connect( builder.ConnectionString, configuration ); 75 | } 76 | 77 | /// 78 | /// 通过集成身份验证登陆 PostgreSQL 数据库,以创建 PostgreSQL 数据库访问器 79 | /// 80 | /// 数据库服务器实例名称 81 | /// 数据库名称 82 | /// 数据库端口 83 | /// 是否启用连接池(默认启用) 84 | /// PostgreSQL数据库配置 85 | /// SQL Server 数据库访问器 86 | public static NpgsqlDbExecutor Connect( string host, string database, int port = 5432, bool pooling = true, NpgsqlDbConfiguration configuration = null ) 87 | { 88 | var builder = new NpgsqlConnectionStringBuilder 89 | { 90 | Host = host, 91 | Port = port, 92 | Database = database, 93 | IntegratedSecurity = true, 94 | Pooling = pooling 95 | }; 96 | 97 | return Connect( builder.ConnectionString, configuration ); 98 | } 99 | 100 | public static NpgsqlDbExecutor Connect( string host, string database = null, int port = 5432, bool? integratedSecurity = null, string userID = null, string password = null, string attachDbFilename = null, bool? pooling = null, int? maxPoolSize = null, int? minPoolSize = null, NpgsqlDbConfiguration configuration = null ) 101 | { 102 | var builder = new NpgsqlConnectionStringBuilder 103 | { 104 | Host = host 105 | }; 106 | 107 | if ( userID != null ) 108 | builder.UserName = userID; 109 | 110 | if ( password != null ) 111 | builder.Password = password; 112 | 113 | if ( integratedSecurity != null ) 114 | builder.IntegratedSecurity = integratedSecurity.Value; 115 | 116 | if ( database != null ) 117 | builder.Database = database; 118 | 119 | if ( port > 0 ) 120 | builder.Port = port; 121 | 122 | if ( pooling != null ) 123 | builder.Pooling = pooling.Value; 124 | 125 | if ( maxPoolSize != null ) 126 | builder.MaxPoolSize = maxPoolSize.Value; 127 | 128 | if ( minPoolSize != null ) 129 | builder.MaxPoolSize = minPoolSize.Value; 130 | 131 | return Connect( builder.ConnectionString, configuration ); 132 | } 133 | 134 | private static NpgsqlDbConfiguration _defaultConfiguration = new NpgsqlDbConfiguration(); 135 | 136 | /// 137 | /// 获取或设置默认配置 138 | /// 139 | public static NpgsqlDbConfiguration DefaultConfiguration 140 | { 141 | get { return _defaultConfiguration; } 142 | set 143 | { 144 | _defaultConfiguration = value ?? new NpgsqlDbConfiguration(); 145 | } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/PostgreSqlClient/NpgsqlDbConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data.Common; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Ivony.Data.PostgreSQL.PostgreSqlClient 7 | { 8 | public class NpgsqlDbConfiguration : DbConfiguration { } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/PostgreSqlClient/NpgsqlDbTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Data.Common; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Ivony.Data.Common; 6 | using Npgsql; 7 | 8 | namespace Ivony.Data.PostgreSQL.PostgreSqlClient 9 | { 10 | /// 11 | /// PostgreSql 数据库事务上下文对象 12 | /// 13 | public class NpgsqlDbTransactionContext : DbTransactionContextBase 14 | { 15 | private readonly NpgsqlDbExecutor _executor; 16 | 17 | internal NpgsqlDbTransactionContext(string connectionString, NpgsqlDbConfiguration configuration) 18 | { 19 | this.Connection = new NpgsqlConnection(connectionString); 20 | this._executor = new NpgsqlDbExecutorWithTransaction(this, configuration); 21 | } 22 | 23 | #region Overrides of DbTransactionContextBase 24 | 25 | /// 26 | /// 派生类实现此方法以创建数据库事务对象 27 | /// 28 | /// 数据库事务对象 29 | protected override NpgsqlTransaction CreateTransaction() 30 | { 31 | if (this.Connection.State == ConnectionState.Closed) 32 | { 33 | this.Connection.Open(); 34 | } 35 | 36 | return this.Connection.BeginTransaction(); 37 | } 38 | 39 | /// 40 | /// 获取在事务中执行查询的执行器 41 | /// 42 | public override NpgsqlDbExecutor DbExecutor 43 | { 44 | get { return this._executor; } 45 | } 46 | 47 | #endregion 48 | 49 | public NpgsqlConnection Connection { get; private set; } 50 | 51 | internal class NpgsqlDbExecutorWithTransaction : NpgsqlDbExecutor 52 | { 53 | public NpgsqlDbExecutorWithTransaction(NpgsqlDbTransactionContext transaction, NpgsqlDbConfiguration configuration) 54 | : base( transaction.Connection.ConnectionString, configuration ) 55 | { 56 | this.TransactionContext = transaction; 57 | } 58 | 59 | /// 60 | /// 当前所处的事务 61 | /// 62 | protected NpgsqlDbTransactionContext TransactionContext { get; private set; } 63 | 64 | /// 65 | /// 重写 ExecuteAsync 方法,在事务中异步执行查询 66 | /// 67 | /// 要执行的查询命令 68 | /// 取消指示 69 | /// 用于追踪的追踪器 70 | /// 查询执行上下文 71 | protected sealed override async Task ExecuteAsync(NpgsqlCommand command, CancellationToken token, IDbTracing tracing = null) 72 | { 73 | try 74 | { 75 | TryExecuteTracing(tracing, t => t.OnExecuting(command)); 76 | 77 | command.Connection = TransactionContext.Connection; 78 | command.Transaction = TransactionContext.Transaction; 79 | 80 | if ( Configuration.QueryExecutingTimeout.HasValue ) 81 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 82 | 83 | 84 | var reader = await command.ExecuteReaderAsync(token); 85 | var context = new NpgsqlDbExecuteContext(TransactionContext, reader, tracing); 86 | 87 | TryExecuteTracing(tracing, t => t.OnLoadingData(context)); 88 | 89 | return context; 90 | } 91 | catch (DbException exception) 92 | { 93 | TryExecuteTracing(tracing, t => t.OnException(exception)); 94 | 95 | throw; 96 | } 97 | 98 | } 99 | 100 | 101 | /// 102 | /// 执行查询命令并返回执行上下文 103 | /// 104 | /// 查询命令 105 | /// 用于追踪查询过程的追踪器 106 | /// 查询执行上下文 107 | protected sealed override IDbExecuteContext Execute(NpgsqlCommand command, IDbTracing tracing = null) 108 | { 109 | try 110 | { 111 | TryExecuteTracing(tracing, t => t.OnExecuting(command)); 112 | 113 | command.Connection = TransactionContext.Connection; 114 | command.Transaction = TransactionContext.Transaction; 115 | 116 | if ( Configuration.QueryExecutingTimeout.HasValue ) 117 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 118 | 119 | 120 | var reader = command.ExecuteReader(); 121 | var context = new NpgsqlDbExecuteContext(TransactionContext, reader, tracing); 122 | 123 | TryExecuteTracing(tracing, t => t.OnLoadingData(context)); 124 | 125 | return context; 126 | } 127 | catch (DbException exception) 128 | { 129 | TryExecuteTracing(tracing, t => t.OnException(exception)); 130 | 131 | throw; 132 | } 133 | } 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/PostgreSqlClient/NpgsqlExecuteContext.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Common; 2 | using Ivony.Data.Common; 3 | using Npgsql; 4 | 5 | namespace Ivony.Data.PostgreSQL.PostgreSqlClient 6 | { 7 | public class NpgsqlDbExecuteContext : AsyncDbExecuteContextBase 8 | { 9 | /// 10 | /// 创建 NpgsqlExecuteContext 对象 11 | /// 12 | /// PostgreSql 数据库连接 13 | /// PostgreSql 数据读取器 14 | /// 用于当前查询的追踪器 15 | public NpgsqlDbExecuteContext( NpgsqlConnection connection, DbDataReader dataReader, IDbTracing tracing ) 16 | : base( dataReader, tracing, connection ) 17 | { 18 | this.NpgsqlDataReader = dataReader; 19 | } 20 | 21 | /// 22 | /// 创建 NpgsqlExecuteContext 对象 23 | /// 24 | /// PostgreSql 数据库事务上下文 25 | /// PostgreSql 数据读取器 26 | /// 用于当前查询的追踪器 27 | public NpgsqlDbExecuteContext( NpgsqlDbTransactionContext transaction, DbDataReader dataReader, IDbTracing tracing ) 28 | : base( dataReader, tracing, null ) 29 | { 30 | this.TransactionContext = transaction; 31 | this.NpgsqlDataReader = dataReader; 32 | } 33 | 34 | public DbDataReader NpgsqlDataReader { get; private set; } 35 | 36 | /// 37 | /// 数据库事务上下文,如果有的话 38 | /// 39 | public NpgsqlDbTransactionContext TransactionContext { get; private set; } 40 | } 41 | } -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/PostgreSqlClient/NpgsqlParameterizedQueryParser.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Npgsql; 3 | 4 | namespace Ivony.Data.PostgreSQL.PostgreSqlClient 5 | { 6 | /// 7 | /// 定义 PostgreSQL 参数化查询解析器。 8 | /// 9 | public class NpgsqlParameterizedQueryParser : ParameterizedQueryParser 10 | { 11 | /// 12 | /// 派生类实现此方法产生一个参数对象,并生成一段占位符字符串。 13 | /// 14 | /// 参数值 15 | /// 参数索引位置 16 | /// 参数对象 17 | /// 参数占位符 18 | protected override string GetParameterPlaceholder( object value, int index, out NpgsqlParameter parameter ) 19 | { 20 | var name = "@Param" + index; 21 | parameter = new NpgsqlParameter( name, value ); 22 | 23 | return name; 24 | } 25 | 26 | /// 27 | /// 创建命令对象 28 | /// 29 | /// 命令文本 30 | /// 命令参数 31 | /// 命令对象 32 | protected override NpgsqlCommand CreateCommand( string commandText, NpgsqlParameter[] parameters ) 33 | { 34 | var command = new NpgsqlCommand 35 | { 36 | CommandText = commandText 37 | }; 38 | 39 | command.Parameters.AddRange( parameters ); 40 | 41 | return command; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("DbWrench PostgreSQL Provider")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct( "DbWrench PostgreSQL Provider" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2009 Ivony & JRoger Licensed under the Apache License, Version 2.0" )] 14 | [assembly: AssemblyTrademark( "DbWrench" )] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("1d45a0ea-9d4d-43f8-a030-69d68fae0590")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyFileVersion("1.0")] 37 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.PostgreSQL/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/Ivony.Data.SQLite.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7388FD8C-4D38-457F-A5D0-0C006ABBF15B} 8 | Library 9 | Properties 10 | Ivony.Data 11 | DbWrench.SQLite 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | False 38 | ..\packages\System.Data.SQLite.Core.MSIL.1.0.92.0\lib\net45\System.Data.SQLite.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {27d46d02-f7bc-42b2-ae3e-33eb5b1fa3f9} 57 | Ivony.Data 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("DbWrench SQLite Provider")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct( "DbWrench SQLite Provider" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2009 Ivony Licensed under the Apache License, Version 2.0" )] 14 | [assembly: AssemblyTrademark( "DbWrench" )] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("6476dad1-ab3a-424c-80ae-7d90197f18d7")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyFileVersion("1.0")] -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/SQLite.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.SQLiteClient; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data.SQLite; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data 11 | { 12 | public static class SQLite 13 | { 14 | 15 | 16 | /// 17 | /// 根据连接字符串连接到指定的 SQLite 服务器 18 | /// 19 | /// 连接字符串 20 | /// SQLite 数据库配置 21 | /// SQLite 数据库访问器 22 | public static SQLiteExecutor Connect( string connectionString, SQLiteConfiguration configuration = null ) 23 | { 24 | return new SQLiteExecutor( connectionString, configuration ); 25 | } 26 | 27 | 28 | /// 29 | /// 连接到指定的数据库文件 30 | /// 31 | /// 数据库文件路径 32 | /// 如果数据库文件不存在,是否自动创建(默认为true) 33 | /// SQLite 数据库配置 34 | /// SQLite 数据库访问器 35 | public static SQLiteExecutor ConnectFile( string filepath, bool create = true, SQLiteConfiguration configuration = null ) 36 | { 37 | 38 | if ( !File.Exists( filepath ) ) 39 | { 40 | if ( create ) 41 | { 42 | Directory.CreateDirectory( Path.GetDirectoryName( filepath ) ); 43 | SQLiteConnection.CreateFile( filepath ); 44 | } 45 | 46 | else 47 | throw new FileNotFoundException( "要连接的数据库文件不存在" ); 48 | } 49 | 50 | var builder = new SQLiteConnectionStringBuilder(); 51 | builder.DataSource = filepath; 52 | 53 | return Connect( builder.ConnectionString, configuration ?? DefaultConfiguration ); 54 | } 55 | 56 | 57 | 58 | /// 59 | /// 创建一个空白的数据库文件并连接 60 | /// 61 | /// 文件路径 62 | /// 若文件已经存在是否覆盖(默认为false) 63 | /// SQLite 数据库配置 64 | /// SQLite 数据库访问器 65 | public static SQLiteExecutor ConnectNewFile( string filepath, bool overwrite = false, SQLiteConfiguration configuration = null ) 66 | { 67 | 68 | if ( File.Exists( filepath ) ) 69 | { 70 | if ( overwrite ) 71 | File.Delete( filepath ); 72 | 73 | else 74 | throw new InvalidOperationException( "文件已存在" ); 75 | } 76 | 77 | SQLiteConnection.CreateFile( filepath ); 78 | 79 | return ConnectFile( filepath, false, configuration ); 80 | } 81 | 82 | 83 | 84 | 85 | static SQLite() 86 | { 87 | DefaultConfiguration = new SQLiteConfiguration(); 88 | } 89 | 90 | public static SQLiteConfiguration DefaultConfiguration 91 | { 92 | get; 93 | private set; 94 | 95 | 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/SQLiteClient/SQLiteConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Ivony.Data.SQLiteClient 7 | { 8 | public class SQLiteConfiguration : DbConfiguration 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/SQLiteClient/SQLiteExecuteContext.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data.SQLite; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace Ivony.Data.SQLiteClient 9 | { 10 | class SQLiteExecuteContext : DbExecuteContextBase 11 | { 12 | public SQLiteExecuteContext( SQLiteDataReader dataReader, IDbTracing tracing, object sync ) 13 | : base( dataReader, tracing, sync: sync ) 14 | { 15 | DataReader = dataReader; 16 | } 17 | 18 | 19 | public new SQLiteDataReader DataReader 20 | { 21 | get; 22 | private set; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/SQLiteClient/SQLiteExecutor.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Ivony.Data.Queries; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using System.Data.Common; 7 | using System.Data.SQLite; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Ivony.Data.SQLiteClient 13 | { 14 | 15 | 16 | /// 17 | /// 用于操作 SQLite 的数据库访问工具 18 | /// 19 | public class SQLiteExecutor : DbExecutorBase, IDbExecutor 20 | { 21 | 22 | public SQLiteExecutor( string connectionString, SQLiteConfiguration configuration ) 23 | : base( configuration ) 24 | { 25 | Configuration = configuration; 26 | 27 | Connection = new SQLiteConnection( connectionString ); 28 | SyncRoot = new object(); 29 | } 30 | 31 | protected SQLiteConnection Connection 32 | { 33 | get; 34 | private set; 35 | } 36 | 37 | 38 | protected SQLiteConfiguration Configuration 39 | { 40 | get; 41 | private set; 42 | } 43 | 44 | 45 | 46 | public object SyncRoot 47 | { 48 | get; 49 | private set; 50 | } 51 | 52 | 53 | 54 | public IDbExecuteContext Execute( ParameterizedQuery query ) 55 | { 56 | var tracing = TryCreateTracing( this, query ); 57 | var command = new SQLiteParameterizedQueryParser().Parse( query ); 58 | 59 | return Execute( command, tracing ); 60 | } 61 | 62 | private IDbExecuteContext Execute( SQLiteCommand command, IDbTracing tracing ) 63 | { 64 | try 65 | { 66 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 67 | 68 | 69 | if ( Connection.State == ConnectionState.Closed ) 70 | Connection.Open(); 71 | command.Connection = Connection; 72 | 73 | if ( Configuration.QueryExecutingTimeout.HasValue ) 74 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 75 | 76 | 77 | var context = new SQLiteExecuteContext( command.ExecuteReader(), tracing, SyncRoot ); 78 | 79 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 80 | 81 | return context; 82 | } 83 | catch ( DbException exception ) 84 | { 85 | TryExecuteTracing( tracing, t => t.OnException( exception ) ); 86 | throw; 87 | } 88 | 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/SQLiteClient/SQLiteParameterizedQueryParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Ivony.Data.Queries; 7 | using System.Data.SQLite; 8 | using Ivony.Data.Common; 9 | 10 | namespace Ivony.Data.SQLiteClient 11 | { 12 | 13 | 14 | /// 15 | /// 用于转换参数化查询为 SQLiteCommand 对象的参数化查询解析器。 16 | /// 17 | public class SQLiteParameterizedQueryParser : ParameterizedQueryParser 18 | { 19 | protected override string GetParameterPlaceholder( object value, int index, out SQLiteParameter parameter ) 20 | { 21 | var name = ":Param" + index; 22 | parameter = new SQLiteParameter( name, value ); 23 | return name; 24 | 25 | } 26 | 27 | protected override SQLiteCommand CreateCommand( string commandText, SQLiteParameter[] parameters ) 28 | { 29 | var command = new SQLiteCommand( commandText ); 30 | command.Parameters.AddRange( parameters ); 31 | return command; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.SQLite/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/MySqlTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Linq; 4 | using Ivony.Data.MySqlClient; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Ivony.Data.Queries; 7 | 8 | namespace Ivony.Data.Test 9 | { 10 | //[TestClass] 11 | public class MySqlTest 12 | { 13 | private TestTraceService traceService; 14 | private MySqlDbExecutor db; 15 | public MySqlTest() 16 | { 17 | traceService = new TestTraceService(); 18 | db = MySqlDb.Connect( "localhost", "Test", "root", "", configuration: new MySqlDbConfiguration() { TraceService = traceService } ); 19 | db.T( "DROP TABLE IF EXISTS testTable" ).ExecuteNonQuery(); 20 | db.T( @" 21 | CREATE TABLE testTable( 22 | Id int(11) NOT NULL, 23 | Name varchar(50) DEFAULT NULL, 24 | Content text, 25 | PRIMARY KEY (Id) 26 | )" ).ExecuteNonQuery(); 27 | } 28 | [TestInitialize] 29 | public void Initialize() 30 | { 31 | db.T( "TRUNCATE TABLE testTable" ).ExecuteNonQuery(); 32 | } 33 | [TestMethod] 34 | public void StandardTest() 35 | { 36 | Assert.IsNull( db.T( "SELECT * FROM testTable" ).ExecuteScalar(), "空数据表查询测试失败!" ); 37 | Assert.IsNull( db.T( "SELECT * FROM testTable" ).ExecuteFirstRow(), "空数据表查询测试失败!" ); 38 | 39 | Assert.AreEqual( db.T( "SELECT COUNT(*) FROM testTable" ).ExecuteScalar(), 0, "空数据表查询测试失败" ); 40 | Assert.AreEqual( db.T( "INSERT INTO testTable ( Name, Content) VALUES ( {...} )", "Ivony", "Test" ).ExecuteNonQuery(), 1, "插入数据测试失败" ); 41 | Assert.AreEqual( db.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 1, "插入数据后查询测试失败" ); 42 | Assert.IsNotNull( db.T( "SELECT ID FROM testTable" ).ExecuteFirstRow(), "插入数据后查询测试失败" ); 43 | 44 | var dataItem = db.T( "SELECT * FROM testTable" ).ExecuteDynamicObject(); 45 | Assert.AreEqual( dataItem.Name, "Ivony", "插入数据后查询测试失败" ); 46 | Assert.AreEqual( dataItem["Content"], "Test", "插入数据后查询测试失败" ); 47 | } 48 | 49 | [TestMethod] 50 | public void TransactionTest() 51 | { 52 | 53 | using ( var transaction = db.BeginTransaction() ) 54 | { 55 | Assert.AreEqual( transaction.T( "INSERT INTO testTable ( Name, Content ) VALUES ( {...} )", "Ivony", "Test" ).ExecuteNonQuery(), 1, "插入数据测试失败" ); 56 | Assert.AreEqual( transaction.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 1, "插入数据后查询测试失败" ); 57 | } 58 | 59 | Assert.AreEqual( db.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 0, "自动回滚事务测试失败" ); 60 | 61 | using ( var transaction = db.BeginTransaction() ) 62 | { 63 | Assert.AreEqual( transaction.T( "INSERT INTO testTable ( Name, Content) VALUES ( {...} )", "Ivony", "Test" ).ExecuteNonQuery(), 1, "插入数据测试失败" ); 64 | Assert.AreEqual( transaction.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 1, "插入数据后查询测试失败" ); 65 | 66 | transaction.Rollback(); 67 | } 68 | 69 | Assert.AreEqual( db.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 0, "手动回滚事务测试失败" ); 70 | 71 | 72 | 73 | using ( var transaction = db.BeginTransaction() ) 74 | { 75 | Assert.AreEqual( transaction.T( "INSERT INTO testTable ( Name, Content) VALUES ( {...} )", "Ivony", "Test" ).ExecuteNonQuery(), 1, "插入数据测试失败" ); 76 | Assert.AreEqual( transaction.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 1, "插入数据后查询测试失败" ); 77 | 78 | transaction.Commit(); 79 | } 80 | 81 | Assert.AreEqual( db.T( "SELECT * FROM testTable" ).ExecuteDynamics().Length, 1, "手动提交事务测试失败" ); 82 | 83 | 84 | 85 | { 86 | Exception exception = null; 87 | var transaction = (MySqlDbTransactionContext) db.BeginTransaction(); 88 | 89 | try 90 | { 91 | using ( transaction ) 92 | { 93 | transaction.T( "SELECT * FROM Nothing" ).ExecuteNonQuery(); 94 | transaction.Commit(); 95 | } 96 | } 97 | catch ( Exception e ) 98 | { 99 | exception = e; 100 | } 101 | 102 | Assert.IsNotNull( exception, "事务中出现异常测试失败" ); 103 | Assert.AreEqual( transaction.Connection.State, ConnectionState.Closed ); 104 | } 105 | } 106 | 107 | [TestMethod] 108 | public void TraceTest() 109 | { 110 | 111 | db.T( "SELECT * FROM testTable" ).ExecuteDataTable(); 112 | 113 | var tracing = traceService.Last(); 114 | 115 | var logs = tracing.TraceEvents; 116 | Assert.AreEqual( logs.Length, 3 ); 117 | 118 | Assert.AreEqual( logs[0].EventName, "OnExecuting" ); 119 | Assert.AreEqual( logs[1].EventName, "OnLoadingData" ); 120 | Assert.AreEqual( logs[2].EventName, "OnComplete" ); 121 | 122 | 123 | try 124 | { 125 | db.T( "SELECT * FROM Nothing" ).ExecuteDynamics(); 126 | } 127 | catch 128 | { 129 | 130 | } 131 | 132 | tracing = traceService.Last(); 133 | 134 | logs = tracing.TraceEvents; 135 | Assert.AreEqual( logs.Length, 2 ); 136 | 137 | Assert.AreEqual( logs[0].EventName, "OnExecuting" ); 138 | Assert.AreEqual( logs[1].EventName, "OnException" ); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/PostgreSqlTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Ivony.Data.PostgreSQL; 9 | using Ivony.Data.PostgreSQL.PostgreSqlClient; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using Npgsql; 12 | 13 | namespace Ivony.Data.Test 14 | { 15 | //[TestClass] 16 | public class PostgreSqlTests 17 | { 18 | private NpgsqlDbExecutor _db; 19 | 20 | [TestInitialize] 21 | public void Initialize() 22 | { 23 | //this._db = PostgreSql.Create("Server=127.0.0.1;Port=5432;Database=InventoryDB;User Id=inventory_user;Password=sa", new NpgsqlDbConfiguration()); 24 | this._db = PostgreSql.Connect("127.0.0.1", "InventoryDB", 5432, "inventory_user", "sa"); 25 | } 26 | 27 | [TestMethod] 28 | public void NpgsqlTest() 29 | { 30 | //var dt = this._db.T("SELECT * FROM \"J_Log\" LIMIT 1 OFFSET 0").ExecuteDataTable(); 31 | 32 | //Assert.IsNotNull(dt); 33 | //Assert.IsTrue(dt.Rows.Count == 1); 34 | 35 | //var affectedRows = this._db.T("INSERT INTO \"J_Log\" (\"LoginUser\",\"CreationDate\",\"Action\") VALUES ( {...} )", "oger", DateTime.Now, 1).ExecuteNonQuery(); 36 | 37 | //Assert.AreEqual(affectedRows, 1, "插入数据失败"); 38 | 39 | var dr = this._db.T("SELECT \"Id\" FROM \"J_Log\"").ExecuteFirstRow(); 40 | 41 | Assert.IsNotNull(dr, "插入数据后查询测试失败"); 42 | 43 | var dynamicVar = this._db.T("SELECT * FROM \"J_Log\"").ExecuteDynamics(); 44 | 45 | Assert.AreEqual(dynamicVar.Length, 61, "插入数据后查询测试失败"); 46 | } 47 | 48 | [TestMethod] 49 | public async Task NpgsqlAsyncTest() 50 | { 51 | var dt = await this._db.T("SELECT * FROM \"J_Log\" LIMIT 1 OFFSET 0").ExecuteDataTableAsync(); 52 | 53 | Assert.IsNotNull(dt); 54 | Assert.IsTrue(dt.Rows.Count == 1); 55 | 56 | //var affectedRows = await this._db.T("INSERT INTO \"J_Log\" (\"LoginUser\",\"CreationDate\",\"Action\") VALUES ( {...} )", "oger", DateTime.Now, 1).ExecuteNonQueryAsync(); 57 | 58 | //Assert.AreEqual(affectedRows, 1, "插入数据失败"); 59 | 60 | var dr = await this._db.T("SELECT \"Id\" FROM \"J_Log\"").ExecuteFirstRowAsync(); 61 | 62 | Assert.IsNotNull(dr, "插入数据后查询测试失败"); 63 | 64 | var dynamicVar = await this._db.T("SELECT * FROM \"J_Log\"").ExecuteDynamicsAsync(); 65 | 66 | Assert.AreEqual(dynamicVar.Length, 62, "插入数据后查询测试失败"); 67 | } 68 | 69 | [TestMethod] 70 | public void NpgsqlTransactionTest() 71 | { 72 | //using (var tran = this._db.BeginTransaction()) 73 | //{ 74 | // var beforTranCount = this._db.T("SELECT \"count\"(\"Id\") FROM \"J_Log\"").ExecuteScalar(); 75 | // var affectedRows = this._db.T("INSERT INTO \"J_Log\" (\"LoginUser\",\"CreationDate\",\"Action\") VALUES ( {...} )", "oger", DateTime.Now, 1).ExecuteNonQuery(); 76 | 77 | // tran.Commit(); 78 | 79 | // var afterCommitCount = this._db.T("SELECT \"count\"(\"Id\") FROM \"J_Log\"").ExecuteScalar(); 80 | 81 | // Assert.IsTrue(affectedRows == 1, "插入数据失败"); 82 | // Assert.IsTrue(afterCommitCount - beforTranCount == 1, "提交事务失败"); 83 | //} 84 | 85 | 86 | 87 | var beforTranCount = this._db.T("SELECT \"count\"(\"Id\") FROM \"J_Log\"").ExecuteScalar(); 88 | 89 | using (var tran = this._db.BeginTransaction()) 90 | { 91 | var affectedRows = tran.T("INSERT INTO \"J_Log\" (\"LoginUser\",\"CreationDate\",\"Action\") VALUES ( {...} )", "oger", DateTime.Now, 1).ExecuteNonQuery(); 92 | 93 | tran.Rollback(); 94 | //tran.Commit(); 95 | } 96 | 97 | var afterCommitCount = this._db.T("SELECT \"count\"(\"Id\") FROM \"J_Log\"").ExecuteScalar(); 98 | 99 | Assert.IsTrue(afterCommitCount == beforTranCount, "事务回滚失败"); 100 | } 101 | 102 | [TestMethod] 103 | public void MyTestTransaction() 104 | { 105 | using (var conn = new NpgsqlConnection("Server=127.0.0.1;Port=5432;Database=InventoryDB;User Id=inventory_user;Password=sa")) 106 | { 107 | conn.Open(); 108 | using (var tran = conn.BeginTransaction()) 109 | { 110 | var sql = "INSERT INTO \"J_Log\" (\"LoginUser\",\"CreationDate\",\"Action\") VALUES ( 'oger-me','2014-06-14 12:38:00', 1 )"; 111 | var cmd = new NpgsqlCommand(sql, conn); 112 | 113 | cmd.Transaction = tran; 114 | 115 | var affectedRows = cmd.ExecuteNonQuery(); 116 | 117 | Trace.WriteLine(affectedRows); 118 | 119 | tran.Rollback(); 120 | } 121 | } 122 | } 123 | } 124 | 125 | 126 | } 127 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下特性集 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle( "Ivony.Data.Test" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "Ivony.Data.Test" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2014" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 请将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible( false )] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid( "e906c330-c374-4a50-827b-8b316db42bac" )] 24 | 25 | // 程序集的版本信息由以下四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion( "1.0.0.0" )] 36 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 37 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/SQLiteTest.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.SQLiteClient; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data.SQLite; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data.Test 11 | { 12 | 13 | //[TestClass] 14 | public class SQLiteTest 15 | { 16 | 17 | SQLiteExecutor db; 18 | 19 | public SQLiteTest() 20 | { 21 | db = SQLite.ConnectFile( @"C:\Temp\1.db" ); 22 | db.T( "DROP TABLE IF EXISTS Test1" ).ExecuteNonQuery(); 23 | db.T( @" 24 | CREATE TABLE [Test1] 25 | ( 26 | [Name] NVARCHAR(50) NOT NULL , 27 | [Content] NTEXT NULL, 28 | [Index] INT NOT NULL 29 | )" ).ExecuteNonQuery(); 30 | } 31 | 32 | 33 | [TestMethod] 34 | public void StandardTest1() 35 | { 36 | Assert.IsNull( db.T( "SELECT Name FROM Test1" ).ExecuteScalar(), "空数据表查询测试失败" ); 37 | Assert.IsNull( db.T( "SELECT Name FROM Test1" ).ExecuteFirstRow(), "空数据表查询测试失败" ); 38 | Assert.AreEqual( db.T( "SELECT COUNT(*) FROM Test1" ).ExecuteScalar(), 0, "空数据表查询测试失败" ); 39 | Assert.AreEqual( db.T( "INSERT INTO Test1 ( Name, Content, [Index] ) VALUES ( {...} )", "Ivony", "Test", 1 ).ExecuteNonQuery(), 1, "插入数据测试失败" ); 40 | Assert.AreEqual( db.T( "SELECT * FROM Test1" ).ExecuteDynamics().Length, 1, "插入数据后查询测试失败" ); 41 | Assert.IsNotNull( db.T( "SELECT Name FROM Test1" ).ExecuteFirstRow(), "插入数据后查询测试失败" ); 42 | 43 | var dataItem = db.T( "SELECT * FROM Test1" ).ExecuteDynamicObject(); 44 | Assert.AreEqual( dataItem.Name, "Ivony", "插入数据后查询测试失败" ); 45 | Assert.AreEqual( dataItem["Content"], "Test", "插入数据后查询测试失败" ); 46 | } 47 | 48 | [TestCleanup] 49 | public void Shutdown() 50 | { 51 | System.Data.SQLite.SQLiteConnection.Shutdown( true, false ); 52 | SQLiteConnection.ClearAllPools(); 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/TestTraceService.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Ivony.Logs; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data.Test 11 | { 12 | public class TestTraceService : IDbTraceService, IEnumerable 13 | { 14 | 15 | 16 | IList _list = new List(); 17 | 18 | 19 | public IDbTracing CreateTracing( IDbExecutor executor, TQuery query ) where TQuery : IDbQuery 20 | { 21 | var tracing = new DbTracing( query ); 22 | _list.Add( tracing ); 23 | return tracing; 24 | 25 | } 26 | 27 | 28 | 29 | 30 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 31 | { 32 | return _list.GetEnumerator(); 33 | } 34 | 35 | IEnumerator IEnumerable.GetEnumerator() 36 | { 37 | return _list.GetEnumerator(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/x64/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/Ivony.Data.Test/x64/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/Ivony.Data.Test/x86/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/Ivony.Data.Test/x86/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/DataTableAdapter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.Common; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data.Common 10 | { 11 | /// 12 | /// 定义用于填充 DataTable 的 DataAdapter 13 | /// 14 | public class DataTableAdapter : DataAdapter 15 | { 16 | 17 | 18 | /// 19 | /// 使用指定范围内的行填充 DataTable 并返回。 20 | /// 21 | /// 用来读取数据的 DataReader 22 | /// 要填充的起始记录位置 23 | /// 最多填充的记录条数 24 | /// 填充好的 DataTable 25 | public DataTable FillDataTable( IDataReader dataReader, int startRecord, int maxRecords ) 26 | { 27 | var dataTable = new DataTable(); 28 | base.Fill( new[] { dataTable }, dataReader, startRecord, maxRecords ); 29 | 30 | return dataTable; 31 | } 32 | 33 | /// 34 | /// 从 DataReader 中读取所有数据并填充一个 DataSet 返回。 35 | /// 36 | /// 用来读取数据的 DataReader 37 | /// 填充好的 DataTable 38 | public DataSet FillDataSet( IDataReader dataReader ) 39 | { 40 | var dataSet = new DataSet(); 41 | base.Fill( dataSet, "Result", dataReader, 0, 0 ); 42 | return dataSet; 43 | } 44 | 45 | 46 | #if !NET40 47 | /// 48 | /// 使用指定范围内的行异步填充 DataTable 并返回。 49 | /// 50 | /// 用来读取数据的 DataReader 51 | /// 要填充的起始记录位置 52 | /// 最多填充的记录条数 53 | /// 填充好的 DataTable 54 | public async Task FillDataTableAsync( DbDataReader dataReader, int startRecord, int maxRecords ) 55 | { 56 | 57 | var dataTable = new DataTable(); 58 | 59 | base.FillSchema( dataTable, SchemaType.Source, dataReader ); 60 | 61 | var array = new object[dataReader.FieldCount]; 62 | 63 | while ( await dataReader.ReadAsync() ) 64 | { 65 | dataReader.GetValues( array ); 66 | dataTable.LoadDataRow( array, true ); 67 | } 68 | 69 | return dataTable; 70 | } 71 | #endif 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/DbExecutorBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data.Common 8 | { 9 | 10 | /// 11 | /// 辅助实现数据库查询器的基类 12 | /// 13 | public abstract class DbExecutorBase 14 | { 15 | 16 | 17 | private DbConfiguration _configuration; 18 | 19 | 20 | /// 21 | /// 初始化 DbExecuterBase 类型 22 | /// 23 | /// 当前要使用的数据库配置 24 | protected DbExecutorBase( DbConfiguration configuration ) 25 | { 26 | _configuration = configuration; 27 | TraceService = configuration.TraceService; 28 | } 29 | 30 | 31 | /// 32 | /// 获取在追踪数据库查询过程的追踪服务 33 | /// 34 | protected IDbTraceService TraceService 35 | { 36 | get; 37 | private set; 38 | } 39 | 40 | 41 | 42 | /// 43 | /// 尝试创建 IDbTracing 对象 44 | /// 45 | /// 即将执行的查询的类型 46 | /// 查询执行器 47 | /// 即将执行的查询对象 48 | /// 追踪该查询执行过程的 IDbTracing 对象 49 | protected IDbTracing TryCreateTracing( IDbExecutor executor, TQuery query ) where TQuery : IDbQuery 50 | { 51 | 52 | if ( TraceService == null ) 53 | return null; 54 | 55 | IDbTracing tracing; 56 | try 57 | { 58 | tracing = TraceService.CreateTracing( executor, query ); 59 | } 60 | catch 61 | { 62 | return null; 63 | } 64 | 65 | return tracing; 66 | } 67 | 68 | 69 | 70 | 71 | /// 72 | /// 尝试创建 IDbTracing 对象 73 | /// 74 | /// 即将执行的查询的类型 75 | /// 即将执行的查询对象 76 | /// 追踪该查询执行过程的 IDbTracing 对象 77 | protected IDbTracing TryCreateTracing( TQuery query ) where TQuery : IDbQuery 78 | { 79 | 80 | return TryCreateTracing( (IDbExecutor) this, query ); 81 | 82 | } 83 | 84 | 85 | 86 | /// 87 | /// 尝试执行查询追踪器的一个追踪方法,此方法会自动判断追踪器是否存在以及对调用中出现的异常进行异常屏蔽。 88 | /// 89 | /// 查询追踪器,如果有的话 90 | /// 要执行的追踪操作 91 | protected void TryExecuteTracing( IDbTracing tracing, Action action ) 92 | { 93 | if ( tracing == null ) 94 | return; 95 | 96 | try 97 | { 98 | action( tracing ); 99 | } 100 | catch 101 | { 102 | 103 | } 104 | } 105 | 106 | 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/DbTransactionContextBase.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data.Common 10 | { 11 | 12 | 13 | /// 14 | /// 辅助实现 IDbTransactionContext 的抽象基类 15 | /// 16 | public abstract class DbTransactionContextBase : IDbTransactionContext where TDbTransaction : IDbTransaction 17 | { 18 | 19 | 20 | private bool _completed = false; 21 | private bool _disposed = false; 22 | 23 | private object _sync = new object(); 24 | 25 | 26 | 27 | 28 | /// 29 | /// 获取数据库事务对象 30 | /// 31 | public TDbTransaction Transaction 32 | { 33 | get; 34 | private set; 35 | } 36 | 37 | 38 | 39 | private IDbConnection _connection; 40 | 41 | /// 42 | /// 开启数据库事务 43 | /// 44 | public virtual void BeginTransaction() 45 | { 46 | 47 | lock ( SyncRoot ) 48 | { 49 | Transaction = CreateTransaction(); 50 | _connection = Transaction.Connection; 51 | } 52 | } 53 | 54 | 55 | /// 56 | /// 派生类实现此方法以创建数据库事务对象 57 | /// 58 | /// 数据库事务对象 59 | protected abstract TDbTransaction CreateTransaction(); 60 | 61 | 62 | 63 | /// 64 | /// 提交事务 65 | /// 66 | public virtual void Commit() 67 | { 68 | lock ( SyncRoot ) 69 | { 70 | 71 | if ( Transaction == null ) 72 | throw new InvalidOperationException(); 73 | 74 | try 75 | { 76 | Transaction.Commit(); 77 | _completed = true; 78 | } 79 | finally 80 | { 81 | if ( _connection.State != ConnectionState.Closed ) 82 | _connection.Close(); 83 | } 84 | } 85 | } 86 | 87 | 88 | /// 89 | /// 回滚事务 90 | /// 91 | public virtual void Rollback() 92 | { 93 | lock ( SyncRoot ) 94 | { 95 | 96 | if ( Transaction == null ) 97 | throw new InvalidOperationException(); 98 | 99 | try 100 | { 101 | Transaction.Rollback(); 102 | _completed = true; 103 | } 104 | finally 105 | { 106 | if ( _connection.State != ConnectionState.Closed ) 107 | _connection.Close(); 108 | } 109 | } 110 | } 111 | 112 | 113 | 114 | /// 115 | /// 获取在事务中执行查询的执行器 116 | /// 117 | public abstract TDbExecutor DbExecutor 118 | { 119 | get; 120 | } 121 | 122 | 123 | 124 | /// 125 | /// 销毁事务对象,若事务尚未提交,则会自动回滚 126 | /// 127 | public virtual void Dispose() 128 | { 129 | 130 | lock ( SyncRoot ) 131 | { 132 | 133 | if ( Transaction == null ) 134 | return; 135 | 136 | 137 | if ( _disposed ) 138 | throw new ObjectDisposedException( GetType().Name ); 139 | 140 | if ( _completed ) 141 | { 142 | _disposed = true; 143 | return; 144 | } 145 | 146 | Rollback(); 147 | } 148 | } 149 | 150 | 151 | /// 152 | /// 获取用于同步的对象 153 | /// 154 | public virtual object SyncRoot 155 | { 156 | get { return _sync; } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/IDbProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Ivony.Data.Common 7 | { 8 | 9 | /// 10 | /// 定义 IDbExecutor 的提供程序 11 | /// 12 | public interface IDbProvider 13 | { 14 | 15 | /// 16 | /// 获取指定类型查询的查询器 17 | /// 18 | /// 指定类型的查询 19 | /// 连接字符串 20 | /// 数据库查询器 21 | IDbExecutor GetDbExecutor( string connectionString ) where T : IDbQuery; 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/IParameterizedQueryParser.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Queries; 2 | using System; 3 | 4 | 5 | namespace Ivony.Data.Common 6 | { 7 | 8 | /// 9 | /// 定义参数化查询解析器 10 | /// 11 | /// 解析完成的命令对象的类型 12 | public interface IParameterizedQueryParser 13 | { 14 | /// 15 | /// 创建查询命令对象 16 | /// 17 | /// 参数化查询 18 | /// 查询命令对象 19 | TCommand Parse( ParameterizedQuery query ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/ParameterizedQueryLiteralValueParser.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Queries; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data.Common 9 | { 10 | 11 | /// 12 | /// 辅助实现 IParameterizedQueryParser 的基类 13 | /// 14 | /// 解析完成的命令对象的类型 15 | public abstract class ParameterizedQueryLiteralValueParser : IParameterizedQueryParser 16 | { 17 | 18 | 19 | /// 20 | /// 创建查询命令 21 | /// 22 | /// 参数化查询 23 | /// 查询命令 24 | public TCommand Parse( ParameterizedQuery query ) 25 | { 26 | 27 | var regex = ParameterizedQuery.ParameterPlaceholdRegex; 28 | 29 | 30 | 31 | 32 | var text = regex.Replace( query.TextTemplate, ( match ) => 33 | { 34 | var index = int.Parse( match.Groups["index"].Value ); 35 | 36 | return GetLiteralValue( DbValueConverter.ConvertTo( query.ParameterValues[index], null ) ); 37 | 38 | } ); 39 | 40 | 41 | return CreateCommand( text.Replace( "##", "#" ) ); 42 | } 43 | 44 | /// 45 | /// 派生类实现此方法以创建命令对象 46 | /// 47 | /// 命令文本 48 | /// 49 | protected abstract TCommand CreateCommand( string commandText ); 50 | 51 | 52 | /// 53 | /// 获取指定参数值在查询命令中的表达式 54 | /// 55 | /// 参数值 56 | /// 该参数值在查询命令中的字面表达方式 57 | protected abstract string GetLiteralValue( object value ); 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/ParameterizedQueryParser.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Queries; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data.Common 9 | { 10 | /// 11 | /// 辅助实现 IParameterizedQueryParser 的基类 12 | /// 13 | /// 解析完成的命令对象的类型 14 | /// 命令参数对象的类型 15 | public abstract class ParameterizedQueryParser : IParameterizedQueryParser 16 | { 17 | 18 | 19 | private object _sync = new object(); 20 | 21 | /// 22 | /// 获取用于同步的对象 23 | /// 24 | public virtual object SyncRoot 25 | { 26 | get { return _sync; } 27 | } 28 | 29 | /// 30 | /// 创建查询命令 31 | /// 32 | /// 参数化查询 33 | /// 查询命令 34 | public TCommand Parse( ParameterizedQuery query ) 35 | { 36 | 37 | 38 | var length = query.ParameterValues.Length; 39 | 40 | TParameter[] parameters = new TParameter[length]; 41 | string[] parameterPlaceholders = new string[length]; 42 | 43 | lock ( SyncRoot ) 44 | { 45 | var regex = ParameterizedQuery.ParameterPlaceholdRegex; 46 | 47 | var text = regex.Replace( query.TextTemplate, ( match ) => 48 | { 49 | var index = int.Parse( match.Groups["index"].Value ); 50 | 51 | if ( index >= length ) 52 | throw new IndexOutOfRangeException( "分析参数化查询时遇到错误,参数索引超出边界" ); 53 | 54 | var placeholder = parameterPlaceholders[index]; 55 | if ( placeholder == null ) 56 | placeholder = parameterPlaceholders[index] = GetParameterPlaceholder( DbValueConverter.ConvertTo( query.ParameterValues[index], null ), index, out parameters[index] ); 57 | 58 | return placeholder; 59 | } ); 60 | 61 | 62 | return CreateCommand( text.Replace( "##", "#" ), parameters.ToArray() ); 63 | } 64 | } 65 | 66 | 67 | /// 68 | /// 派生类实现此方法产生一个参数对象,并生成一段占位符字符串。 69 | /// 70 | /// 参数值 71 | /// 参数索引位置 72 | /// 参数对象 73 | /// 参数占位符 74 | protected abstract string GetParameterPlaceholder( object value, int index, out TParameter parameter ); 75 | 76 | 77 | /// 78 | /// 创建命令对象 79 | /// 80 | /// 命令文本 81 | /// 命令参数 82 | /// 命令对象 83 | protected abstract TCommand CreateCommand( string commandText, TParameter[] parameters ); 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Common/XmlDocumentValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml.Linq; 8 | 9 | namespace Ivony.Data.Common 10 | { 11 | 12 | /// 13 | /// 用于对 XDocument 类型对象和数据对象进行双向转换的转换器 14 | /// 15 | public class XDocumentValueConverter : IDbValueConverter 16 | { 17 | XDocument IDbValueConverter.ConvertValueFrom( object dataValue, string dataTypeName ) 18 | { 19 | 20 | if ( dataValue == null || Convert.IsDBNull( dataValue ) ) 21 | return null; 22 | 23 | var text = (string) dataValue; 24 | return XDocument.Parse( text ); 25 | 26 | } 27 | 28 | object IDbValueConverter.ConvertValueTo( object value, string dataTypeName ) 29 | { 30 | if ( value == null ) 31 | return null; 32 | 33 | return ((XDocument) value).ToString( SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/DataSetExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Data; 6 | using System.Threading.Tasks; 7 | using Ivony.Data.Common; 8 | 9 | 10 | namespace Ivony.Data 11 | { 12 | /// 13 | /// 为系统的 DataSet 和 DataTable 对象提供扩展方法 14 | /// 15 | public static class DataSetExtensions 16 | { 17 | 18 | /// 19 | /// 将 DataTable 转换为易于数据绑定的 DataRowView 对象列表 20 | /// 21 | /// 要转换的 DataTable 22 | /// 易于数据绑定的形式 23 | public static IEnumerable GetRowViews( this DataTable table ) 24 | { 25 | return table.DefaultView.Cast(); 26 | } 27 | 28 | 29 | /// 30 | /// 获取 DataRow 列表 31 | /// 32 | /// 要转换的 DataTable 33 | /// DataRow 列表 34 | public static IEnumerable GetRows( this DataTable table ) 35 | { 36 | return table.Rows.Cast(); 37 | } 38 | 39 | 40 | /// 41 | /// 将 DataTable 转换为易于数据绑定的 IDictionary<string, object> 对象列表 42 | /// 43 | /// 要转换的 DataTable 44 | /// 易于数据绑定的形式 45 | public static IEnumerable> AsDictionaries( this DataTable table ) 46 | { 47 | return GetRowViews( table ).Select( item => CreateDictionary( item, table ) ); 48 | } 49 | 50 | private static IDictionary CreateDictionary( DataRowView item, DataTable table ) 51 | { 52 | var result = new Dictionary( table.CaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase ); 53 | foreach ( DataColumn column in table.Columns ) 54 | result.Add( column.ColumnName, item[column.ColumnName] ); 55 | 56 | return result; 57 | } 58 | 59 | 60 | 61 | 62 | /// 63 | /// 获取第一列数据 64 | /// 65 | /// 列数据类型 66 | /// 数据对象 67 | /// 68 | public static T[] Column( this DataTable table ) 69 | { 70 | return table.Rows.Cast().Select( item => item.FieldValue( 0 ) ).ToArray(); 71 | } 72 | 73 | /// 74 | /// 获取指定列数据 75 | /// 76 | /// 列数据类型 77 | /// 数据对象 78 | /// 列名 79 | /// 80 | public static T[] Column( this DataTable table, string columnName ) 81 | { 82 | return table.Rows.Cast().Select( item => item.FieldValue( columnName ) ).ToArray(); 83 | } 84 | 85 | 86 | /// 87 | /// 将 DataRow 转换为等效的 Dictionary 88 | /// 89 | /// 要转换的 DataRow 90 | /// 等效的 Dictionary 91 | public static IDictionary ToDictionary( this DataRow dataItem ) 92 | { 93 | 94 | IDictionary result; 95 | 96 | var table = dataItem.Table; 97 | if ( table.CaseSensitive ) 98 | result = new Dictionary( StringComparer.Ordinal ); 99 | else 100 | result = new Dictionary( StringComparer.OrdinalIgnoreCase ); 101 | 102 | foreach ( DataColumn column in table.Columns ) 103 | result.Add( column.ColumnName, dataItem[column] ); 104 | 105 | return result; 106 | } 107 | 108 | 109 | /// 110 | /// 将 DataTable 转换为等效的 Dictionary 数组 111 | /// 112 | /// 要转换的 DataTable 113 | /// 等效的 Dictionary 114 | public static IDictionary[] ToDictionaries( this DataTable data ) 115 | { 116 | return data.Rows.Cast().Where( r => r.RowState == DataRowState.Unchanged ).Select( r => ToDictionary( r ) ).ToArray(); 117 | } 118 | 119 | 120 | 121 | /// 122 | /// 执行查询并返回第一列数据 123 | /// 124 | /// 列类型 125 | /// 要执行的查询 126 | /// 第一列的数据 127 | public static T[] ExecuteFirstColumn( this IDbExecutableQuery query ) 128 | { 129 | return query.ExecuteDataTable().Column(); 130 | } 131 | 132 | #if !NET40 133 | /// 134 | /// 异步执行查询并返回第一列数据 135 | /// 136 | /// 列类型 137 | /// 要执行的查询 138 | /// 第一列的数据 139 | public async static Task ExecuteFirstColumnAsync( this IAsyncDbExecutableQuery query ) 140 | { 141 | return (await query.ExecuteDataTableAsync()).Column(); 142 | } 143 | #endif 144 | 145 | 146 | /// 147 | /// 执行查询并将数据转换为 DataRowView 集合返回 148 | /// 149 | /// 要执行的查询 150 | /// 转换为 DataRowView 的数据集合 151 | public static IEnumerable ExecuteDataRowViews( this IDbExecutableQuery query ) 152 | { 153 | return query.ExecuteDataTable().GetRowViews(); 154 | } 155 | 156 | 157 | #if !NET40 158 | /// 159 | /// 异步执行查询并将数据转换为 DataRowView 集合返回 160 | /// 161 | /// 要执行的查询 162 | /// 转换为 DataRowView 的数据集合 163 | public async static Task> ExecuteDataRowViewsAsync( this IAsyncDbExecutableQuery query ) 164 | { 165 | return (await query.ExecuteDataTableAsync()).GetRowViews(); 166 | } 167 | #endif 168 | 169 | 170 | /// 171 | /// 执行查询并将第一行数据数据转换为 DataRowView 返回 172 | /// 173 | /// 要执行的查询 174 | /// 转换为 DataRowView 的数据集合 175 | public static DataRowView ExecuteFirstDataRowView( this IDbExecutableQuery query ) 176 | { 177 | return query.ExecuteDataTable().GetRowViews().FirstOrDefault(); 178 | } 179 | 180 | #if !NET40 181 | /// 182 | /// 异步执行查询并将第一行数据数据转换为 DataRowView 返回 183 | /// 184 | /// 要执行的查询 185 | /// 转换为 DataRowView 的数据集合 186 | public async static Task ExecuteFirstDataRowViewAsync( this IAsyncDbExecutableQuery query ) 187 | { 188 | return (await query.ExecuteDataTableAsync()).GetRowViews().FirstOrDefault(); 189 | } 190 | #endif 191 | 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Db.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using Ivony.Data.Queries; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data 11 | { 12 | 13 | /// 14 | /// 提供一系列静态方法辅助访问数据库 15 | /// 16 | public static class Db 17 | { 18 | 19 | 20 | 21 | /// 22 | /// 解析模板表达式,创建参数化查询对象 23 | /// 24 | /// 参数化模板 25 | /// 参数化查询 26 | public static ParameterizedQuery Template( FormattableString formatTemplate ) 27 | { 28 | return new ParameterizedQuery( formatTemplate ); 29 | } 30 | 31 | 32 | /// 33 | /// 解析模板表达式,创建参数化查询对象 34 | /// 35 | /// 模板文本 36 | /// 模板参数 37 | /// 参数化查询 38 | public static ParameterizedQuery Template( string templateText, params object[] args ) 39 | { 40 | if ( args == null ) 41 | args = new object[] { null }; 42 | 43 | if ( AllowNonObjectArrayAsArgs ) 44 | { 45 | if ( args.Length == 1 ) 46 | { 47 | var array = args[0] as Array; 48 | if ( array != null ) 49 | { 50 | args = new object[array.Length]; 51 | array.CopyTo( args, 0 ); 52 | } 53 | } 54 | } 55 | else 56 | { 57 | if ( args.GetType() != typeof( object[] ) ) 58 | args = new object[] { args }; 59 | } 60 | 61 | 62 | return TemplateParser.ParseTemplate( templateText, args ); 63 | } 64 | 65 | 66 | 67 | /// 68 | /// 解析模板表达式,创建参数化查询对象 69 | /// 70 | /// 模板文本 71 | /// 模板参数 72 | /// 参数化查询 73 | public static ParameterizedQuery T( string templateText, params object[] args ) 74 | { 75 | return Template( templateText, args ); 76 | } 77 | 78 | 79 | 80 | /// 81 | /// 允许非 object[] 类型的数组对象作为多参数列表使用,即允许任意类型数组展开成参数列表。 82 | /// 83 | public static bool AllowNonObjectArrayAsArgs { get; set; } 84 | 85 | 86 | /// 87 | /// 通过连接字符串设置,创建指定类型查询的执行器。 88 | /// 89 | /// 要执行的查询类型 90 | /// 连接字符串名 91 | /// 执行器 92 | public static IDbExecutor CreateExecutor( string connectionStringName ) where T : IDbQuery 93 | { 94 | var connectionStringSetting = ConfigurationManager.ConnectionStrings[connectionStringName]; 95 | var provider = GetDbProvider( connectionStringSetting.ProviderName ); 96 | 97 | if ( provider == null ) 98 | return null; 99 | 100 | return provider.GetDbExecutor( connectionStringSetting.ConnectionString ); 101 | } 102 | 103 | private static IDbProvider GetDbProvider( string name ) 104 | { 105 | return null; 106 | } 107 | 108 | 109 | 110 | /// 111 | /// 将多个参数化查询串联起来并用指定的字符串分隔 112 | /// 113 | /// 分隔符 114 | /// 参数化查询 115 | /// 串联后的结果 116 | public static ParameterizedQuery Join( this string sperator, params ParameterizedQuery[] queries ) 117 | { 118 | 119 | if ( queries == null ) 120 | throw new ArgumentNullException( "queries" ); 121 | 122 | 123 | queries = queries.Where( i => i != null ).ToArray();//去除所有为 null 的参数化查询对象 124 | if ( !queries.Any() ) 125 | return null; 126 | 127 | var builder = new ParameterizedQueryBuilder(); 128 | queries[0].AppendTo( builder ); 129 | 130 | foreach ( var q in queries.Skip( 1 ) ) 131 | { 132 | if ( !builder.IsEndWithWhiteSpace() && !char.IsWhiteSpace( sperator[0] ) && Db.AddWhiteSpaceOnConcat ) 133 | builder.Append( ' ' ); 134 | 135 | builder.AppendText( sperator ); 136 | 137 | if ( !builder.IsEndWithWhiteSpace() && !q.IsStartWithWhiteSpace() && Db.AddWhiteSpaceOnConcat ) 138 | builder.Append( ' ' ); 139 | 140 | builder.AppendPartial( q ); 141 | } 142 | 143 | 144 | return builder.CreateQuery(); 145 | } 146 | 147 | 148 | 149 | static Db() 150 | { 151 | AddWhiteSpaceOnConcat = true; 152 | } 153 | 154 | 155 | /// 156 | /// 获取或设置当串联两个参数化查询时,是否应当自动插入空白字符。 157 | /// 158 | internal static bool AddWhiteSpaceOnConcat 159 | { 160 | get; 161 | set; 162 | } 163 | 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/DbConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | 11 | /// 12 | /// 定义通用的数据库配置项 13 | /// 14 | public class DbConfiguration 15 | { 16 | 17 | 18 | /// 19 | /// 创建默认的通用数据库配置 20 | /// 21 | public DbConfiguration() { } 22 | 23 | 24 | /// 25 | /// 从现有配置中创建通用数据库配置 26 | /// 27 | public DbConfiguration( DbConfiguration configuration ) 28 | { 29 | 30 | TraceService = configuration.TraceService; 31 | QueryExecutingTimeout = configuration.QueryExecutingTimeout; 32 | 33 | } 34 | 35 | 36 | /// 37 | /// 获取或设置在执行数据库查询过程中提供追踪服务的对象 38 | /// 39 | public IDbTraceService TraceService 40 | { 41 | get; 42 | set; 43 | } 44 | 45 | 46 | 47 | /// 48 | /// 获取或设置执行默认的查询超时时间 49 | /// 50 | public TimeSpan? QueryExecutingTimeout 51 | { 52 | get; 53 | set; 54 | } 55 | 56 | 57 | 58 | /// 59 | /// 获取或设置当串联两个参数化查询时,是否应当自动插入空白字符。(此配置为全局配置) 60 | /// 61 | public bool AddWhiteSpaceOnConcat 62 | { 63 | get { return Db.AddWhiteSpaceOnConcat; } 64 | set { Db.AddWhiteSpaceOnConcat = value; } 65 | } 66 | 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/DbExecutableQuery.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data 11 | { 12 | 13 | /// 14 | /// IDbExecutableQuery 的一个标准实现 15 | /// 16 | /// 查询对象的类型 17 | public sealed class DbExecutableQuery : IDbExecutableQuery, IDbQueryContainer where T : IDbQuery 18 | { 19 | 20 | 21 | /// 22 | /// 创建 DbExecutableQuery 对象 23 | /// 24 | /// 可以执行查询的执行器 25 | /// 要执行的查询 26 | public DbExecutableQuery( IDbExecutor executor, T query ) 27 | { 28 | Executor = executor; 29 | Query = query; 30 | } 31 | 32 | /// 33 | /// 用于同步执行查询的执行器 34 | /// 35 | public IDbExecutor Executor { get; private set; } 36 | 37 | 38 | /// 39 | /// 要执行的查询对象 40 | /// 41 | public T Query { get; private set; } 42 | 43 | 44 | /// 45 | /// 同步执行查询 46 | /// 47 | /// 查询执行上下文 48 | public IDbExecuteContext Execute() 49 | { 50 | return Executor.Execute( Query ); 51 | } 52 | 53 | 54 | /// 55 | /// 定义隐式类型转换,将 DbExecutableQuery 转换为实际的查询对象 56 | /// 57 | /// 58 | /// 59 | public static implicit operator T( DbExecutableQuery executable ) 60 | { 61 | return executable.Query; 62 | } 63 | 64 | 65 | IDbQuery IDbQueryContainer.Query 66 | { 67 | get { return Query; } 68 | } 69 | } 70 | 71 | 72 | /// 73 | /// IAsyncDbExecutableQuery 的标准实现 74 | /// 75 | /// 查询类型 76 | public sealed class AsyncDbExecutableQuery : IAsyncDbExecutableQuery, IDbQueryContainer where T : IDbQuery 77 | { 78 | 79 | /// 80 | /// 创建 AsyncDbExecutableQuery 对象 81 | /// 82 | /// 可以执行查询的执行器 83 | /// 要执行的查询 84 | public AsyncDbExecutableQuery( IAsyncDbExecutor executor, T query ) 85 | { 86 | Executor = executor; 87 | Query = query; 88 | } 89 | 90 | 91 | 92 | /// 93 | /// 用于异步执行查询的查询器 94 | /// 95 | public IAsyncDbExecutor Executor { get; private set; } 96 | 97 | 98 | /// 99 | /// 要执行的查询对象 100 | /// 101 | public T Query { get; private set; } 102 | 103 | 104 | /// 105 | /// 定义隐式类型转换,将 DbExecutableQuery 转换为实际的查询对象 106 | /// 107 | /// 可异步执行的查询 108 | /// 109 | public static implicit operator T( AsyncDbExecutableQuery executable ) 110 | { 111 | return executable.Query; 112 | } 113 | 114 | 115 | IDbQuery IDbQueryContainer.Query 116 | { 117 | get { return Query; } 118 | } 119 | 120 | 121 | 122 | /// 123 | /// 同步执行查询 124 | /// 125 | /// 查询执行上下文 126 | [System.ComponentModel.EditorBrowsable( System.ComponentModel.EditorBrowsableState.Advanced )] 127 | public IDbExecuteContext Execute() 128 | { 129 | return Executor.Execute( Query ); 130 | } 131 | 132 | #if !NET40 133 | /// 134 | /// 异步执行查询 135 | /// 136 | /// 异步查询执行上下文 137 | [System.ComponentModel.EditorBrowsable( System.ComponentModel.EditorBrowsableState.Advanced )] 138 | public Task ExecuteAsync( CancellationToken token = default( CancellationToken ) ) 139 | { 140 | return Executor.ExecuteAsync( Query, token ); 141 | } 142 | #endif 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/DbTracing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | 11 | 12 | /// 13 | /// IDbTracing 的一个标准实现 14 | /// 15 | public sealed class DbTracing : IDbTracing 16 | { 17 | 18 | 19 | /// 20 | /// 创建一个 DbTracing 实例 21 | /// 22 | /// 即将执行的查询对象 23 | public DbTracing( IDbQuery query ) : this( query, null ) { } 24 | 25 | 26 | 27 | /// 28 | /// 创建一个 DbTracing 实例 29 | /// 30 | /// 即将执行的查询对象 31 | /// 当查询执行完成之后需要回调的方法 32 | public DbTracing( IDbQuery query, Action complateCallback ) 33 | { 34 | 35 | QueryObject = query; 36 | 37 | ExecutionTime = TimeSpan.Zero; 38 | QueryTime = TimeSpan.Zero; 39 | 40 | 41 | callback = complateCallback; 42 | } 43 | 44 | 45 | 46 | 47 | private Stopwatch executionStopwatch = new Stopwatch(); 48 | private Stopwatch queryStopwatch = new Stopwatch(); 49 | 50 | 51 | 52 | /// 53 | /// 获取此次查询执行的查询对象 54 | /// 55 | public IDbQuery QueryObject 56 | { 57 | get; 58 | private set; 59 | } 60 | 61 | /// 62 | /// 获取此次查询执行的命令对象 63 | /// 64 | public object CommandObject 65 | { 66 | get; 67 | private set; 68 | } 69 | 70 | 71 | 72 | /// 73 | /// 数据库查询执行时间 74 | /// 75 | public TimeSpan ExecutionTime 76 | { 77 | get; 78 | private set; 79 | } 80 | 81 | 82 | /// 83 | /// 总计查询时间(即查询执行时间+数据读取时间) 84 | /// 85 | public TimeSpan QueryTime 86 | { 87 | get; 88 | private set; 89 | } 90 | 91 | 92 | /// 93 | /// 获取查询中出现的异常(如果有的话) 94 | /// 95 | public Exception Exception 96 | { 97 | get; 98 | private set; 99 | } 100 | 101 | 102 | 103 | private List events = new List(); 104 | 105 | 106 | /// 107 | /// 获取查询过程中所出现的事件列表 108 | /// 109 | public TraceEventDescriptor[] TraceEvents 110 | { 111 | get { return events.ToArray(); } 112 | } 113 | 114 | 115 | private Action callback; 116 | 117 | 118 | void IDbTracing.OnExecuting( object commandObject ) 119 | { 120 | 121 | events.Add( new TraceEventDescriptor( "OnExecuting", DateTime.UtcNow ) ); 122 | CommandObject = commandObject; 123 | executionStopwatch.Restart(); 124 | queryStopwatch.Restart(); 125 | } 126 | 127 | void IDbTracing.OnLoadingData( IDbExecuteContext context ) 128 | { 129 | events.Add( new TraceEventDescriptor( "OnLoadingData", DateTime.UtcNow ) ); 130 | executionStopwatch.Stop(); 131 | ExecutionTime = executionStopwatch.Elapsed; 132 | } 133 | 134 | void IDbTracing.OnComplete() 135 | { 136 | if ( Exception != null )//如果已经因为异常而退出,则不再执行 Complete 逻辑 137 | return; 138 | 139 | 140 | events.Add( new TraceEventDescriptor( "OnComplete", DateTime.UtcNow ) ); 141 | queryStopwatch.Stop(); 142 | QueryTime = queryStopwatch.Elapsed; 143 | 144 | if ( callback != null ) 145 | callback( this ); 146 | } 147 | 148 | void IDbTracing.OnException( Exception exception ) 149 | { 150 | events.Add( new TraceEventDescriptor( "OnException", DateTime.UtcNow ) ); 151 | executionStopwatch.Stop(); 152 | queryStopwatch.Stop(); 153 | 154 | QueryTime = queryStopwatch.Elapsed; 155 | 156 | Exception = exception; 157 | 158 | if ( callback != null ) 159 | callback( this ); 160 | } 161 | 162 | 163 | 164 | 165 | /// 166 | /// 定义 DbTracing 在追踪过程中发生的事件的描述 167 | /// 168 | public struct TraceEventDescriptor 169 | { 170 | 171 | internal TraceEventDescriptor( string name, DateTime time ) 172 | { 173 | _time = time; 174 | _eventName = name; 175 | } 176 | 177 | 178 | 179 | private string _eventName; 180 | /// 181 | /// 事件名称 182 | /// 183 | public string EventName { get { return _eventName; } } 184 | 185 | 186 | private DateTime _time; 187 | /// 188 | /// 事件发生时间 189 | /// 190 | public DateTime UtcTime { get { return _time; } } 191 | 192 | } 193 | 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/DbValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data 11 | { 12 | 13 | 14 | /// 15 | /// 提供 IDbValueConverter<T> 的注册点。 16 | /// 17 | public static partial class DbValueConverter 18 | { 19 | 20 | 21 | 22 | /// 23 | /// 是否禁用 Convertible 对象转换(原生对象之间的转换) 24 | /// 25 | public static bool DisableConvertible { get; set; } 26 | 27 | private static class ConverterCache 28 | { 29 | public static IDbValueConverter ConverterInstance { get; set; } 30 | } 31 | 32 | 33 | 34 | private static object sync = new object(); 35 | 36 | private static Dictionary convertToMethodDictionary = new Dictionary(); 37 | private static Dictionary convertFromMethodDictionary = new Dictionary(); 38 | 39 | private delegate object Converter( object value, string dataType ); 40 | 41 | /// 42 | /// 注册一个数据值类型转换器 43 | /// 44 | /// 需要转换的类型 45 | /// 需要注册的转换器 46 | /// 是否覆盖现有的转换器 47 | public static void Register( IDbValueConverter converter, bool overwrite = false ) 48 | { 49 | lock ( sync ) 50 | { 51 | 52 | if ( !overwrite && ConverterCache.ConverterInstance != null ) 53 | throw new InvalidOperationException(); 54 | 55 | ConverterCache.ConverterInstance = converter; 56 | 57 | convertToMethodDictionary[typeof( T )] = converter.ConvertValueTo; 58 | convertFromMethodDictionary[typeof( T )] = ( value, dataType ) => converter.ConvertValueFrom( value, dataType ); 59 | } 60 | } 61 | 62 | 63 | /// 64 | /// 解除数据值类型转换器的注册 65 | /// 66 | /// 转换的类型 67 | public static void Unregister() 68 | { 69 | lock ( sync ) 70 | { 71 | ConverterCache.ConverterInstance = null; 72 | 73 | convertToMethodDictionary.Remove( typeof( T ) ); 74 | convertFromMethodDictionary.Remove( typeof( T ) ); 75 | } 76 | } 77 | 78 | 79 | /// 80 | /// 获取数据值类型转换器 81 | /// 82 | /// 需要转换的类型 83 | /// 84 | public static IDbValueConverter GetConverter() 85 | { 86 | lock ( sync ) 87 | { 88 | return ConverterCache.ConverterInstance; 89 | } 90 | } 91 | 92 | 93 | /// 94 | /// 从数据类型转换为目标类型 95 | /// 96 | /// 目标类型 97 | /// 数据值 98 | /// 数据类型名称 99 | /// 类型转换后的结果 100 | internal static T ConvertFrom( object value, string dataTypeName = null ) 101 | { 102 | var converter = GetConverter(); 103 | if ( converter != null ) 104 | return converter.ConvertValueFrom( value, dataTypeName ); 105 | 106 | return DefaultConverter.Converter( value ); 107 | } 108 | 109 | 110 | 111 | 112 | /// 113 | /// 将值转换为数据库可以接受的类型 114 | /// 115 | /// 所需要转换的值对象 116 | /// 数据库类型名称 117 | /// 数据库可接受的类型 118 | internal static object ConvertTo( object value, string dataTypeName = null ) 119 | { 120 | if ( value == null ) 121 | return DBNull.Value; 122 | 123 | 124 | var type = value.GetType(); 125 | 126 | lock ( sync ) 127 | { 128 | 129 | foreach ( var _type in convertToMethodDictionary.Keys ) 130 | { 131 | if ( _type.IsAssignableFrom( type ) ) 132 | return convertToMethodDictionary[_type]( value, dataTypeName ); 133 | } 134 | } 135 | 136 | return value; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/DefaultConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data 10 | { 11 | public partial class DbValueConverter 12 | { 13 | private class DefaultConverter 14 | { 15 | public static Converter Converter = CreateConverter(); 16 | } 17 | 18 | 19 | private static Converter CreateConverter() 20 | { 21 | var type = typeof( T ); 22 | 23 | var underlyingType = Nullable.GetUnderlyingType( type ); 24 | if ( underlyingType != null ) 25 | { 26 | var methodInfo = typeof( DbValueConverter ).GetMethod( "ConvertNullable", BindingFlags.Static | BindingFlags.NonPublic ).MakeGenericMethod( new Type[] { underlyingType } ); 27 | return (Converter) Delegate.CreateDelegate( typeof( Converter ), methodInfo ); 28 | } 29 | 30 | 31 | else if ( type.IsEnum ) 32 | return ConvertEnum; 33 | 34 | else if ( IsConvertiableType( type ) ) 35 | return ConvertConvertible; 36 | 37 | 38 | else if ( type.IsValueType ) 39 | return ConvertValueType; 40 | 41 | else 42 | return ConvertObject; 43 | } 44 | 45 | 46 | 47 | private static T? ConvertNullable( object value ) where T : struct 48 | { 49 | if ( value == null || Convert.IsDBNull( value ) ) 50 | return null; 51 | 52 | else 53 | return new T?( ConvertFrom( value ) ); 54 | } 55 | 56 | 57 | private static T ConvertEnum( object value ) 58 | { 59 | var enumType = typeof( T ); 60 | 61 | 62 | var str = value as string; 63 | if ( str != null ) 64 | return (T) Enum.Parse( enumType, str ); 65 | 66 | 67 | return (T) Enum.ToObject( enumType, value ); 68 | } 69 | 70 | 71 | 72 | 73 | 74 | private static bool IsConvertiableType( Type type ) 75 | { 76 | var typeCode = Type.GetTypeCode( type ); 77 | 78 | switch ( typeCode ) 79 | { 80 | case TypeCode.String: 81 | case TypeCode.Boolean: 82 | case TypeCode.Byte: 83 | case TypeCode.Char: 84 | case TypeCode.DateTime: 85 | case TypeCode.Decimal: 86 | case TypeCode.Double: 87 | case TypeCode.Int16: 88 | case TypeCode.Int32: 89 | case TypeCode.Int64: 90 | case TypeCode.SByte: 91 | case TypeCode.Single: 92 | case TypeCode.UInt16: 93 | case TypeCode.UInt32: 94 | case TypeCode.UInt64: 95 | return true; 96 | 97 | default: 98 | return false; 99 | } 100 | } 101 | 102 | private static T ConvertConvertible( object value ) 103 | { 104 | 105 | var type = typeof( T ); 106 | 107 | if ( DisableConvertible ) 108 | return (T) value; 109 | 110 | return (T) ConvertConvertible( value, type ); 111 | 112 | } 113 | 114 | private static object ConvertConvertible( object value, Type type ) 115 | { 116 | if ( value == null || Convert.IsDBNull( value ) ) 117 | { 118 | if ( type.IsValueType ) 119 | throw new InvalidCastException( string.Format( CultureInfo.InvariantCulture, "不能将 null 值转换为 {0} 类型对象", type ) ); 120 | 121 | return null; 122 | } 123 | 124 | 125 | var convertible = value as IConvertible; 126 | if ( convertible == null ) 127 | throw new InvalidCastException( string.Format( CultureInfo.InvariantCulture, "无法将 {0} 类型的实例转换为 {1} 类型", value.GetType(), type ) ); 128 | 129 | return convertible.ToType( type, CultureInfo.InvariantCulture ); 130 | 131 | } 132 | 133 | 134 | 135 | private static T ConvertObject( object value ) 136 | { 137 | return (T) value; 138 | } 139 | 140 | private static T ConvertValueType( object value ) 141 | { 142 | if ( value == null || Convert.IsDBNull( value ) ) 143 | throw new InvalidCastException( string.Format( CultureInfo.InvariantCulture, "不能将 null 值转换为 {0} 类型对象", typeof( T ).FullName ) ); 144 | 145 | return (T) value; 146 | 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/EntityConvertAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | /// 11 | /// 用于指定字段名称的特性 12 | /// 13 | [AttributeUsage( AttributeTargets.Property, Inherited = false )] 14 | public class FieldNameAttribute : Attribute 15 | { 16 | /// 17 | /// 创建 FieldNameAttribute 对象 18 | /// 19 | /// 字段名 20 | public FieldNameAttribute( string name ) 21 | { 22 | FieldName = name; 23 | } 24 | 25 | /// 26 | /// 字段名 27 | /// 28 | public string FieldName 29 | { 30 | get; 31 | set; 32 | } 33 | } 34 | 35 | 36 | /// 37 | /// 用于指示属性与任何字段没有关系 38 | /// 39 | [AttributeUsage( AttributeTargets.Property, Inherited = false )] 40 | public class NonFieldAttribute : Attribute 41 | { 42 | } 43 | 44 | 45 | /// 46 | /// 指定类型所应使用的实体转换器 47 | /// 48 | [AttributeUsage( AttributeTargets.Class, Inherited = false )] 49 | public class EntityConvertAttribute : Attribute 50 | { 51 | 52 | private Type _convertType; 53 | 54 | /// 55 | /// 创建 EntityConvertAttribute 对象 56 | /// 57 | /// 实体转换器类型 58 | public EntityConvertAttribute( Type convertType ) 59 | { 60 | _convertType = convertType; 61 | } 62 | 63 | /// 64 | /// 创建实体转换器实例 65 | /// 66 | /// 实体类型 67 | /// 实体转换器实例 68 | public IEntityConverter CreateConverter() 69 | { 70 | return (IEntityConverter) Activator.CreateInstance( _convertType ); 71 | } 72 | 73 | } 74 | 75 | /// 76 | /// 定义实体转换器类型 77 | /// 78 | /// 实体类型 79 | public interface IEntityConverter 80 | { 81 | /// 82 | /// 将数据写入实体 83 | /// 84 | /// 数据行 85 | /// 转换的实体对象 86 | T Convert( DataRow dataItem ); 87 | 88 | /// 89 | /// 是否可重用 90 | /// 91 | bool IsReusable { get; } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbExecutableQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Data.SqlClient; 7 | using System.Threading.Tasks; 8 | using System.Threading; 9 | 10 | namespace Ivony.Data 11 | { 12 | 13 | 14 | /// 15 | /// 定义一个可以执行的查询 16 | /// 17 | public interface IDbExecutableQuery 18 | { 19 | 20 | /// 21 | /// 同步执行查询 22 | /// 23 | /// 24 | IDbExecuteContext Execute(); 25 | 26 | } 27 | 28 | 29 | 30 | /// 31 | /// 定义一个可以异步执行的查询 32 | /// 33 | public interface IAsyncDbExecutableQuery : IDbExecutableQuery 34 | { 35 | #if !NET40 36 | /// 37 | /// 异步执行查询 38 | /// 39 | /// 40 | Task ExecuteAsync( CancellationToken token ); 41 | #endif 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbExecuteContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data 10 | { 11 | 12 | /// 13 | /// 查询执行上下文 14 | /// 15 | public interface IDbExecuteContext : IDisposable 16 | { 17 | 18 | /// 19 | /// 将当前结果集数据填充 DataTable 并返回 20 | /// 21 | /// 填充的起始记录位置 22 | /// 最大要填充的记录条数 23 | /// 填充了数据的 DataTable 24 | DataTable LoadDataTable( int startRecord, int maxRecords ); 25 | 26 | 27 | /// 28 | /// 尝试读取下一个结果集 29 | /// 30 | /// 若存在下一个结果集,则返回 true ,否则返回 false 31 | bool NextResult(); 32 | 33 | 34 | /// 35 | /// 获取更改、插入或删除的行数,如果没有任何行受到影响或语句失败,则为 0。-1 表示是 SELECT 语句。 36 | /// 37 | int RecordsAffected { get; } 38 | 39 | 40 | /// 41 | /// 读取一条记录,并将读取指针推移到下一个位置。 42 | /// 43 | /// 若当前位置存在记录,则返回该记录,否则返回 null 44 | IDataRecord ReadRecord(); 45 | 46 | 47 | 48 | /// 49 | /// 获取用于确保同步查询过程的同步对象 50 | /// 51 | object SyncRoot { get; } 52 | 53 | } 54 | 55 | 56 | 57 | /// 58 | /// 异步查询执行上下文 59 | /// 60 | public interface IAsyncDbExecuteContext : IDbExecuteContext 61 | { 62 | 63 | /// 64 | /// 异步将当前结果集数据填充 DataTable 并返回 65 | /// 66 | /// 填充的起始记录位置 67 | /// 最大要填充的记录条数 68 | /// 取消指示 69 | /// 填充了数据的 DataTable 70 | Task LoadDataTableAsync( int startRecord, int maxRecords, CancellationToken token = default( CancellationToken ) ); 71 | 72 | #if !NET40 73 | /// 74 | /// 尝试异步读取下一个结果集 75 | /// 76 | /// 若存在下一个结果集,则返回 true ,否则返回 false 77 | Task NextResultAsync(); 78 | 79 | 80 | /// 81 | /// 异步读取一条记录,并将读取指针推移到下一个位置。 82 | /// 83 | /// 若当前位置存在记录,则返回该记录,否则返回 null 84 | Task ReadRecordAsync(); 85 | #endif 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbExecutor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data 10 | { 11 | 12 | 13 | /// 14 | /// 定义可以同步执行某类型查询的数据库查询执行程序所需要实现的接口 15 | /// 16 | /// 查询类型 17 | public interface IDbExecutor where T : IDbQuery 18 | { 19 | 20 | /// 21 | /// 执行查询 22 | /// 23 | /// 查询对象 24 | /// 查询执行上下文 25 | IDbExecuteContext Execute( T query ); 26 | 27 | } 28 | 29 | 30 | /// 31 | /// 定义可以异步执行某类型查询的数据库查询执行程序所需要实现的接口 32 | /// 33 | /// 查询类型 34 | public interface IAsyncDbExecutor : IDbExecutor where T : IDbQuery 35 | { 36 | #if !NET40 37 | /// 38 | /// 异步执行查询 39 | /// 40 | /// 要执行的查询 41 | /// 取消指示 42 | /// 查询执行上下文 43 | Task ExecuteAsync( T query, CancellationToken token ); 44 | #endif 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data 8 | { 9 | 10 | /// 11 | /// 这个接口指示该对象是一个可以执行的查询对象 12 | /// 13 | public interface IDbQuery 14 | { 15 | } 16 | 17 | 18 | internal interface IDbQueryContainer 19 | { 20 | 21 | IDbQuery Query { get; } 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbTraceService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data 8 | { 9 | 10 | /// 11 | /// 定义对数据库查询过程进行追踪记录的服务 12 | /// 13 | public interface IDbTraceService 14 | { 15 | 16 | /// 17 | /// 当开始执行一个查询时,框架调用此方法创建一个追踪器,关于这个查询的所有消息,将记录到这个追踪器 18 | /// 19 | /// 正在执行的查询的类型 20 | /// 正在执行查询的查询执行器 21 | /// 正在执行的查询对象 22 | /// 实现类应返回一个追踪器,用于记录日志信息。 23 | IDbTracing CreateTracing( IDbExecutor executor, TQuery query ) where TQuery : IDbQuery; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbTracing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | 11 | /// 12 | /// 定义对数据库查询进行追踪的记录器 13 | /// 14 | public interface IDbTracing 15 | { 16 | 17 | /// 18 | /// 通知追踪记录器正在执行查询 19 | /// 20 | /// 查询命令对象 21 | void OnExecuting( object commandObject ); 22 | 23 | /// 24 | /// 通知追踪记录器正在加载数据。 25 | /// 26 | /// 查询执行上下文 27 | void OnLoadingData( IDbExecuteContext context ); 28 | 29 | /// 30 | /// 通知追踪记录器查询已经全部完成。 31 | /// 32 | void OnComplete(); 33 | 34 | /// 35 | /// 通知追踪记录器查询数据库时出现了异常。 36 | /// 37 | /// 异常信息 38 | void OnException( Exception exception ); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data 8 | { 9 | 10 | 11 | public interface IDbTransactionContext : IDisposable 12 | { 13 | /// 14 | /// 提交事务 15 | /// 16 | void Commit(); 17 | 18 | /// 19 | /// 回滚事务 20 | /// 21 | void Rollback(); 22 | 23 | 24 | /// 25 | /// 开启事务,若事务创建时已经开启,则调用该方法没有副作用 26 | /// 27 | void BeginTransaction(); 28 | } 29 | 30 | /// 31 | /// 定义数据库事务上下文 32 | /// 33 | /// 数据库查询执行程序类型 34 | public interface IDbTransactionContext : IDbTransactionContext 35 | { 36 | 37 | /// 38 | /// 数据库查询执行程序 39 | /// 40 | TDbExecutor DbExecutor { get; } 41 | 42 | /// 43 | /// 获取用于同步的对象 44 | /// 45 | object SyncRoot { get; } 46 | } 47 | 48 | 49 | 50 | /// 51 | /// 定义异步数据库事务上下文 52 | /// 53 | /// 数据查询执行器类型 54 | public interface IAsyncDbTransactionContext : IDbTransactionContext 55 | { 56 | 57 | 58 | /// 59 | /// 异步提交事务 60 | /// 61 | void CommitAsync(); 62 | 63 | /// 64 | /// 异步回滚事务 65 | /// 66 | void RollbackAsync(); 67 | 68 | /// 69 | /// 异步开启事务,若事务创建时已经开启,则调用该方法没有副作用 70 | /// 71 | void BeginTransactionAsync(); 72 | } 73 | 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbTransactionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | 11 | /// 12 | /// 定义数据库事务查询上下文提供程序 13 | /// 14 | /// 数据库查询执行程序类型 15 | public interface IDbTransactionProvider 16 | { 17 | 18 | /// 19 | /// 创建一个数据库事务上下文 20 | /// 21 | /// 数据库事务上下文 22 | IDbTransactionContext CreateTransaction(); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/IDbValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | 11 | 12 | /// 13 | /// 定义数据值类型转换器 14 | /// 15 | /// 要转换的类型 16 | public interface IDbValueConverter 17 | { 18 | 19 | /// 20 | /// 从数据对象转换为特定类型 21 | /// 22 | /// 数据值 23 | /// 参考的数据库数据类型 24 | /// 目标类型的值 25 | T ConvertValueFrom( object dataValue, string dataType ); 26 | 27 | 28 | /// 29 | /// 转换目标类型值为数据 30 | /// 31 | /// 特定类型的值 32 | /// 参考的数据库数据类型(如果有的话) 33 | /// 数据值 34 | object ConvertValueTo( object value, string dataType ); 35 | 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过下列属性集 6 | // 控制。更改这些属性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle( "DbWrench" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "DbWrench" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2009 Ivony Licensed under the Apache License, Version 2.0" )] 14 | [assembly: AssemblyTrademark( "DbWrench" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 属性设置为 true。 20 | [assembly: ComVisible( false )] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid( "974f0833-3125-417e-859a-3c64e8a60dac" )] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 内部版本号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion( "4.0.*" )] 36 | [assembly: AssemblyFileVersion( "4.0" )] 37 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Queries/IParameterizedQueryPartial.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data.Queries 8 | { 9 | /// 10 | /// 定义可以作为参数化查询的片段的对象 11 | /// 12 | public interface IParameterizedQueryPartial 13 | { 14 | /// 15 | /// 将该片段添加到正在构建的参数化查询的末尾 16 | /// 17 | /// 参数化查询构建器 18 | void AppendTo( ParameterizedQueryBuilder builder ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Queries/ParameterArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data.Queries 8 | { 9 | public class ParameterArray : IParameterizedQueryPartial 10 | { 11 | 12 | 13 | private Array _parameters; 14 | private string _separator; 15 | 16 | 17 | public ParameterArray( Array parameters, string separator = ", " ) 18 | { 19 | if ( parameters.Rank != 1 ) 20 | throw new ArgumentException( "参数列表必须是一维数组", "parameters" ); 21 | 22 | _parameters = parameters; 23 | _separator = separator; 24 | } 25 | 26 | public void AppendTo( ParameterizedQueryBuilder builder ) 27 | { 28 | 29 | for ( int i = 0; i < _parameters.Length; i++ ) 30 | { 31 | builder.AppendParameter( _parameters.GetValue( i ) ); 32 | 33 | if ( i < _parameters.Length - 1 ) 34 | builder.AppendText( _separator ); 35 | 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Queries/ParameterizedQuery.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Text.RegularExpressions; 9 | using System.Threading.Tasks; 10 | 11 | namespace Ivony.Data.Queries 12 | { 13 | 14 | /// 15 | /// 代表一个参数化查询 16 | /// 17 | public class ParameterizedQuery : IDbQuery, IParameterizedQueryPartial 18 | { 19 | 20 | /// 21 | /// 定义匹配参数占位符的正则表达式 22 | /// 23 | public static readonly Regex ParameterPlaceholdRegex = new Regex( @"#(?[0-9]+)#", RegexOptions.Compiled ); 24 | 25 | 26 | 27 | /// 28 | /// 获取查询文本模板 29 | /// 30 | public string TextTemplate 31 | { 32 | get; 33 | private set; 34 | } 35 | 36 | 37 | /// 38 | /// 获取参数值 39 | /// 40 | public object[] ParameterValues 41 | { 42 | get; 43 | private set; 44 | } 45 | 46 | 47 | 48 | /// 49 | /// 构建参数化查询对象 50 | /// 51 | /// 查询文本模板 52 | /// 参数值 53 | public ParameterizedQuery( string template, object[] values ) 54 | { 55 | 56 | if ( template == null ) 57 | throw new ArgumentNullException( "template" ); 58 | 59 | if ( values == null ) 60 | throw new ArgumentNullException( "values" ); 61 | 62 | TextTemplate = template; 63 | ParameterValues = new object[values.Length]; 64 | values.CopyTo( ParameterValues, 0 ); 65 | } 66 | 67 | 68 | /// 69 | /// 构建参数化查询对象 70 | /// 71 | /// 查询文本模板 72 | public ParameterizedQuery( FormattableString formatTemplate ) 73 | { 74 | TextTemplate = formatTemplate.Format; 75 | var values = formatTemplate.GetArguments(); 76 | ParameterValues = new object[values.Length]; 77 | values.CopyTo( ParameterValues, 0 ); 78 | } 79 | 80 | 81 | /// 82 | /// 将参数化查询解析为另一个参数化查询的一部分。 83 | /// 84 | /// 参数化查询构建器 85 | public void AppendTo( ParameterizedQueryBuilder builder ) 86 | { 87 | 88 | int index = 0; 89 | 90 | foreach ( Match match in ParameterPlaceholdRegex.Matches( TextTemplate ) ) 91 | { 92 | 93 | var length = match.Index - index; 94 | if ( length > 0 ) 95 | builder.AppendText( TextTemplate.Substring( index, length ) ); 96 | 97 | 98 | var parameterIndex = int.Parse( match.Groups["index"].Value ); 99 | builder.AppendParameter( ParameterValues[parameterIndex] ); 100 | 101 | index = match.Index + match.Length; 102 | } 103 | 104 | builder.AppendText( TextTemplate.Substring( index, TextTemplate.Length - index ) ); 105 | } 106 | 107 | 108 | 109 | /// 110 | /// 重写 ToString 方法,输出参数化查询的字符串表达形式 111 | /// 112 | /// 字符串表达形式 113 | public override string ToString() 114 | { 115 | if ( stringExpression == null ) 116 | stringExpression = GetString(); 117 | 118 | return stringExpression; 119 | } 120 | 121 | private string stringExpression; 122 | 123 | private string GetString() 124 | { 125 | var writer = new StringWriter(); 126 | 127 | writer.WriteLine( "\"" + TextTemplate.Replace( "\"", "\"\"" ) + "\"" ); 128 | writer.WriteLine(); 129 | 130 | for ( int i = 0; i < this.ParameterValues.Length; i++ ) 131 | { 132 | writer.WriteLine( "#{0}#: {1}", i, ParameterValues[i] ); 133 | } 134 | 135 | return writer.ToString(); 136 | } 137 | 138 | 139 | 140 | 141 | /// 142 | /// 提供从字符串到 ParameterizedQuery 的隐式类型转换 143 | /// 144 | /// 要转换为参数化查询的查询字符串 145 | /// 参数化查询对象 146 | public static implicit operator ParameterizedQuery( string text ) 147 | { 148 | return TemplateParser.ParseTemplate( text, new object[0] ); 149 | } 150 | 151 | 152 | /// 153 | /// 串联两个参数化查询对象 154 | /// 155 | /// 第一个参数化查询对象 156 | /// 第二个参数化查询对象 157 | /// 串联后的参数化查询对象 158 | public static ParameterizedQuery operator +( ParameterizedQuery query1, ParameterizedQuery query2 ) 159 | { 160 | return query1.Concat( query2 ); 161 | } 162 | 163 | /// 164 | /// 串联两个参数化查询对象 165 | /// 166 | /// 第一个参数化查询对象 167 | /// 第二个参数化查询对象 168 | /// 串联后的参数化查询对象 169 | public static DbExecutableQuery operator +( DbExecutableQuery query1, ParameterizedQuery query2 ) 170 | { 171 | return query1.Concat( query2 ); 172 | } 173 | 174 | /// 175 | /// 串联两个参数化查询对象 176 | /// 177 | /// 第一个参数化查询对象 178 | /// 第二个参数化查询对象 179 | /// 串联后的参数化查询对象 180 | public static AsyncDbExecutableQuery operator +( AsyncDbExecutableQuery query1, ParameterizedQuery query2 ) 181 | { 182 | return query1.Concat( query2 ); 183 | } 184 | 185 | 186 | internal bool IsStartWithWhiteSpace() 187 | { 188 | return char.IsWhiteSpace( TextTemplate[0] ); 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Queries/ParameterizedQueryBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data.Queries 8 | { 9 | 10 | /// 11 | /// 辅助构建 ParameterizedQuery 对象 12 | /// 13 | public sealed class ParameterizedQueryBuilder 14 | { 15 | 16 | private StringBuilder textBuilder = new StringBuilder(); 17 | 18 | private List values = new List(); 19 | 20 | 21 | private object _sync = new object(); 22 | 23 | 24 | /// 25 | /// 用于同步的对象 26 | /// 27 | public object SyncRoot 28 | { 29 | get { return _sync; } 30 | } 31 | 32 | 33 | /// 34 | /// 添加一段查询文本 35 | /// 36 | /// 要添加到末尾的查询文本 37 | public void AppendText( string text ) 38 | { 39 | lock ( _sync ) 40 | { 41 | textBuilder.Append( text.Replace( "#", "##" ) ); 42 | } 43 | } 44 | 45 | 46 | /// 47 | /// 添加一个字符到查询文本 48 | /// 49 | /// 要添加到查询文本末尾的字符 50 | public void Append( char ch ) 51 | { 52 | lock ( _sync ) 53 | { 54 | if ( ch == '#' ) 55 | textBuilder.Append( "##" ); 56 | 57 | else 58 | textBuilder.Append( ch ); 59 | } 60 | } 61 | 62 | 63 | /// 64 | /// 添加一个查询参数 65 | /// 66 | /// 参数值 67 | public void AppendParameter( object value ) 68 | { 69 | var partial = value as IParameterizedQueryPartial; 70 | if ( partial == null ) 71 | { 72 | var container = value as IDbQueryContainer; 73 | if ( container != null ) 74 | partial = container.Query as IParameterizedQueryPartial; 75 | } 76 | 77 | if ( partial != null ) 78 | { 79 | AppendPartial( partial ); 80 | return; 81 | } 82 | 83 | 84 | lock ( _sync ) 85 | { 86 | values.Add( value ); 87 | textBuilder.AppendFormat( "#{0}#", values.Count - 1 ); 88 | } 89 | } 90 | 91 | 92 | /// 93 | /// 创建参数化查询对象实例 94 | /// 95 | /// 参数化查询对象 96 | public ParameterizedQuery CreateQuery() 97 | { 98 | lock ( _sync ) 99 | { 100 | return new ParameterizedQuery( textBuilder.ToString(), values.ToArray() ); 101 | } 102 | } 103 | 104 | 105 | /// 106 | /// 在当前位置添加一个部分查询 107 | /// 108 | /// 要添加的部分查询对象 109 | public void AppendPartial( IParameterizedQueryPartial partial ) 110 | { 111 | lock ( _sync ) 112 | { 113 | partial.AppendTo( this ); 114 | } 115 | 116 | } 117 | 118 | 119 | 120 | internal bool IsEndWithWhiteSpace() 121 | { 122 | lock ( _sync ) 123 | { 124 | return char.IsWhiteSpace( textBuilder[textBuilder.Length - 1] ); 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Queries/StoredProcedureQuery.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Ivony.Data.Queries 10 | { 11 | /// 12 | /// 存储过程表达式 13 | /// 14 | public class StoredProcedureQuery : IDbQuery 15 | { 16 | 17 | private string _name; 18 | private IDictionary _parameters; 19 | 20 | /// 21 | /// 创建 StoredProcedureExpression 对象 22 | /// 23 | /// 存储过程名称 24 | public StoredProcedureQuery( string name ) : this( name, new Dictionary() ) { } 25 | 26 | /// 27 | /// 创建 StoredProcedureExpression 对象 28 | /// 29 | /// 存储过程名称 30 | /// 存储过程参数列表 31 | public StoredProcedureQuery( string name, IDictionary parameters ) 32 | { 33 | 34 | _name = name; 35 | _parameters = parameters; 36 | 37 | } 38 | 39 | 40 | /// 41 | /// 存储过程名称 42 | /// 43 | public string Name 44 | { 45 | get { return _name; } 46 | } 47 | 48 | /// 49 | /// 存储过程参数列表 50 | /// 51 | public IDictionary Parameters 52 | { 53 | get { return _parameters; } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/Queries/TemplateParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | using Ivony.Data.Queries; 8 | using Ivony.Data.Common; 9 | 10 | namespace Ivony.Data 11 | { 12 | 13 | 14 | /// 15 | /// SQL模板解析器 16 | /// 17 | public class TemplateParser 18 | { 19 | 20 | private static Regex numberRegex = new Regex( @"\G\{(?[0-9]+)\}", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture ); 21 | private static Regex rangeRegex = new Regex( @"\G\{(?[0-9]+)..(?[0-9]+)?\}", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture ); 22 | private static Regex allRegex = new Regex( @"\G\{...\}", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture ); 23 | 24 | 25 | /// 26 | /// 解析查询模板 27 | /// 28 | /// 模板文本 29 | /// 模板参数 30 | /// 解析结果 31 | public static ParameterizedQuery ParseTemplate( string templateText, object[] args ) 32 | { 33 | var builder = new ParameterizedQueryBuilder(); 34 | return ParseTemplate( builder, templateText, args ); 35 | } 36 | 37 | 38 | 39 | /// 40 | /// 解析查询模板 41 | /// 42 | /// 参数化查询构建器 43 | /// 模板文本 44 | /// 模板参数 45 | /// 解析结果 46 | public static ParameterizedQuery ParseTemplate( ParameterizedQueryBuilder builder, string templateText, object[] args ) 47 | { 48 | 49 | if ( args == null ) 50 | throw new ArgumentNullException( "parameters" ); 51 | 52 | lock ( builder.SyncRoot ) 53 | { 54 | 55 | for ( var i = 0; i < templateText.Length; i++ ) 56 | { 57 | 58 | var ch = templateText[i]; 59 | 60 | if ( ch == '{' ) 61 | { 62 | 63 | if ( i == templateText.Length - 1 ) 64 | throw FormatError( templateText, i ); 65 | 66 | if ( templateText[i + 1] == '{' ) 67 | { 68 | i++; 69 | builder.Append( '{' ); 70 | continue; 71 | } 72 | 73 | 74 | 75 | Match match = null; 76 | 77 | do 78 | { 79 | match = numberRegex.Match( templateText, i ); 80 | 81 | if ( match.Success ) 82 | { 83 | 84 | int parameterIndex; 85 | if ( !int.TryParse( match.Groups["index"].Value, out parameterIndex ) ) 86 | throw FormatError( templateText, i ); 87 | 88 | AddParameter( builder, args[parameterIndex] ); 89 | break; 90 | } 91 | 92 | match = rangeRegex.Match( templateText, i ); 93 | if ( match.Success ) 94 | { 95 | int begin, end; 96 | if ( !int.TryParse( match.Groups["begin"].Value, out begin ) ) 97 | throw FormatError( templateText, i ); 98 | 99 | if ( match.Groups["end"] != null ) 100 | { 101 | if ( !int.TryParse( match.Groups["end"].Value, out end ) ) 102 | throw FormatError( templateText, i ); 103 | } 104 | else 105 | end = args.Length - 1; 106 | 107 | 108 | if ( begin > end || end >= args.Length ) 109 | throw FormatError( templateText, i ); 110 | 111 | 112 | AddParameters( builder, args, begin, end ); 113 | break; 114 | } 115 | 116 | 117 | match = allRegex.Match( templateText, i ); 118 | if ( match.Success ) 119 | { 120 | AddParameters( builder, args, 0, args.Length - 1 ); 121 | break; 122 | } 123 | } while ( false ); 124 | 125 | 126 | if ( match == null || !match.Success ) 127 | throw FormatError( templateText, i ); 128 | i += match.Length - 1; 129 | 130 | 131 | } 132 | else if ( ch == '}' ) 133 | { 134 | if ( i == templateText.Length - 1 ) 135 | throw FormatError( templateText, i ); 136 | 137 | if ( templateText[i + 1] == '}' ) 138 | { 139 | i++; 140 | builder.Append( '}' ); 141 | continue; 142 | } 143 | } 144 | 145 | else 146 | builder.Append( ch ); 147 | 148 | } 149 | 150 | 151 | return builder.CreateQuery(); 152 | } 153 | } 154 | 155 | private static FormatException FormatError( string templateText, int i ) 156 | { 157 | return new FormatException( string.Format( "解析字符串 \"{0}\" 时在字符 {1} 处出现问题。", templateText, i ) ); 158 | } 159 | 160 | private static void AddParameters( ParameterizedQueryBuilder builder, object[] parameters, int begin, int end ) 161 | { 162 | var length = end - begin + 1; 163 | var array = new object[length]; 164 | parameters.CopyTo( array, begin ); 165 | 166 | AddParameter( builder, new ParameterArray( array ) ); 167 | } 168 | 169 | private static void AddParameter( ParameterizedQueryBuilder builder, object value ) 170 | { 171 | 172 | var array = value as Array; 173 | if ( array != null && !(array is byte[]) ) 174 | value = new ParameterArray( array ); 175 | 176 | builder.AppendParameter( value ); 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlClient/SqlDbConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ivony.Data.SqlClient 8 | { 9 | /// 10 | /// 定义用于 SQL Server 数据库的配置项 11 | /// 12 | public class SqlDbConfiguration : DbConfiguration 13 | { 14 | 15 | /// 16 | /// 创建一个默认的 SQL Server 数据库配置 17 | /// 18 | public SqlDbConfiguration() { } 19 | 20 | /// 21 | /// 从现有的 SQL Server 数据库配置中创建一个数据库配置 22 | /// 23 | /// 现有的数据库配置 24 | public SqlDbConfiguration( SqlDbConfiguration configuration ) : base( configuration ) { } 25 | 26 | /// 27 | /// 从现有的通用数据库配置文件中创建一个 SQL Server 数据库配置 28 | /// 29 | /// 现有的数据库配置 30 | public SqlDbConfiguration( DbConfiguration configuration ) : base( configuration ) { } 31 | 32 | 33 | /// 34 | /// 获取或设置SQL Server Express LocalDB 默认实例名(此配置为全局配置) 35 | /// 36 | /// 37 | /// 默认值为 v11.0,即 SQL Server Express LocalDB 2012,若需要连接 SQL Server Express LocalDB 2014 ,请使用 MSSQLLocalDB 38 | /// 39 | public string LocalDBInstanceName 40 | { 41 | get { return SqlServer.LocalDBInstanceName; } 42 | set { SqlServer.LocalDBInstanceName = value; } 43 | } 44 | 45 | /// 46 | /// 获取或设置SQL Server Express 默认实例名(此配置为全局配置) 47 | /// 48 | public string ExpressInstanceName 49 | { 50 | get { return SqlServer.ExpressInstanceName; } 51 | set { SqlServer.ExpressInstanceName = value; } 52 | } 53 | 54 | 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlClient/SqlDbExecuteContext.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Data.SqlClient; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace Ivony.Data.SqlClient 12 | { 13 | 14 | 15 | /// 16 | /// 实现 SQL Server 执行上下文 17 | /// 18 | public class SqlDbExecuteContext : AsyncDbExecuteContextBase 19 | { 20 | 21 | 22 | /// 23 | /// 创建 SqlExecuteContext 对象 24 | /// 25 | /// 数据库连接 26 | /// 数据读取器 27 | /// 用于记录此次查询过程的的查询追踪器 28 | internal SqlDbExecuteContext( SqlConnection connection, SqlDataReader reader, IDbTracing tracing ) 29 | : base( reader, tracing, connection ) 30 | { 31 | SqlDataReader = reader; 32 | } 33 | 34 | /// 35 | /// 创建 SqlExecuteContext 对象 36 | /// 37 | /// 数据库事务 38 | /// 数据读取器 39 | /// 用于记录此次查询过程的的查询追踪器 40 | internal SqlDbExecuteContext( SqlDbTransactionContext transaction, SqlDataReader reader, IDbTracing tracing ) 41 | : base( reader, tracing, null ) 42 | { 43 | SqlDataReader = reader; 44 | } 45 | 46 | 47 | /// 48 | /// 数据读取器 49 | /// 50 | public SqlDataReader SqlDataReader 51 | { 52 | get; 53 | private set; 54 | } 55 | 56 | 57 | /// 58 | /// 数据库事务上下文,如果有的话 59 | /// 60 | public SqlDbTransactionContext TransactionContext 61 | { 62 | get; 63 | private set; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlClient/SqlDbExecutor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Data.SqlClient; 5 | using System.Data; 6 | using System.Runtime.Serialization; 7 | using System.Security.Permissions; 8 | using System.Collections; 9 | using System.Configuration; 10 | using System.Threading.Tasks; 11 | using Ivony.Data.Queries; 12 | 13 | using System.Linq; 14 | using System.Threading; 15 | using System.Data.Common; 16 | using Ivony.Data.Common; 17 | 18 | namespace Ivony.Data.SqlClient 19 | { 20 | /// 21 | /// 用于操作 SQL Server 的数据库访问工具 22 | /// 23 | public class SqlDbExecutor : DbExecutorBase, IAsyncDbExecutor, IDbTransactionProvider 24 | { 25 | 26 | 27 | 28 | /// 29 | /// 获取当前连接字符串 30 | /// 31 | protected string ConnectionString 32 | { 33 | get; 34 | private set; 35 | } 36 | 37 | 38 | /// 39 | /// 创建 SqlServer 数据库查询执行程序 40 | /// 41 | /// 连接字符串 42 | /// 当前要使用的数据库配置信息 43 | public SqlDbExecutor( string connectionString, SqlDbConfiguration configuration ) 44 | : base( configuration ) 45 | { 46 | if ( connectionString == null ) 47 | throw new ArgumentNullException( "connectionString" ); 48 | 49 | if ( configuration == null ) 50 | throw new ArgumentNullException( "configuration" ); 51 | 52 | 53 | 54 | ConnectionString = connectionString; 55 | Configuration = configuration; 56 | } 57 | 58 | 59 | /// 60 | /// 当前要使用的数据库配置信息 61 | /// 62 | protected SqlDbConfiguration Configuration 63 | { 64 | get; 65 | private set; 66 | } 67 | 68 | 69 | /// 70 | /// 创建数据库事务上下文 71 | /// 72 | /// 数据库事务上下文 73 | public SqlDbTransactionContext CreateTransaction( IsolationLevel isolationLevel = IsolationLevel.Unspecified) 74 | { 75 | return new SqlDbTransactionContext( ConnectionString, Configuration, isolationLevel ); 76 | } 77 | 78 | 79 | IDbTransactionContext IDbTransactionProvider.CreateTransaction() 80 | { 81 | return CreateTransaction(); 82 | } 83 | 84 | 85 | 86 | /// 87 | /// 执行查询命令并返回执行上下文 88 | /// 89 | /// 查询命令 90 | /// 用于追踪查询过程的追踪器 91 | /// 查询执行上下文 92 | protected virtual IDbExecuteContext Execute( SqlCommand command, IDbTracing tracing = null ) 93 | { 94 | 95 | try 96 | { 97 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 98 | 99 | 100 | var connection = new SqlConnection( ConnectionString ); 101 | connection.Open(); 102 | command.Connection = connection; 103 | 104 | if ( Configuration.QueryExecutingTimeout.HasValue ) 105 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 106 | 107 | 108 | var reader = command.ExecuteReader(); 109 | var context = new SqlDbExecuteContext( connection, reader, tracing ); 110 | 111 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 112 | 113 | return context; 114 | 115 | } 116 | catch ( DbException exception ) 117 | { 118 | TryExecuteTracing( tracing, t => t.OnException( exception ) ); 119 | throw; 120 | } 121 | } 122 | 123 | #if !NET40 124 | /// 125 | /// 异步执行查询命令并返回执行上下文 126 | /// 127 | /// 查询命令 128 | /// 取消指示 129 | /// 用于追踪查询过程的追踪器 130 | /// 查询执行上下文 131 | protected virtual async Task ExecuteAsync( SqlCommand command, CancellationToken token, IDbTracing tracing = null ) 132 | { 133 | try 134 | { 135 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 136 | 137 | var connection = new SqlConnection( ConnectionString ); 138 | await connection.OpenAsync( token ); 139 | command.Connection = connection; 140 | 141 | if ( Configuration.QueryExecutingTimeout.HasValue ) 142 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 143 | 144 | 145 | var reader = await command.ExecuteReaderAsync( token ); 146 | var context = new SqlDbExecuteContext( connection, reader, tracing ); 147 | 148 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 149 | 150 | return context; 151 | } 152 | catch ( DbException exception ) 153 | { 154 | TryExecuteTracing( tracing, t => t.OnException( exception ) ); 155 | throw; 156 | } 157 | } 158 | #endif 159 | 160 | 161 | IDbExecuteContext IDbExecutor.Execute( ParameterizedQuery query ) 162 | { 163 | return Execute( CreateCommand( query ), TryCreateTracing( this, query ) ); 164 | } 165 | 166 | #if !NET40 167 | Task IAsyncDbExecutor.ExecuteAsync( ParameterizedQuery query, CancellationToken token ) 168 | { 169 | return ExecuteAsync( CreateCommand( query ), token, TryCreateTracing( this, query ) ); 170 | } 171 | #endif 172 | 173 | /// 174 | /// 从参数化查询创建查询命令对象 175 | /// 176 | /// 参数化查询对象 177 | /// SQL 查询命令对象 178 | protected SqlCommand CreateCommand( ParameterizedQuery query ) 179 | { 180 | return new SqlParameterizedQueryParser().Parse( query ); 181 | } 182 | 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlClient/SqlDbTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Data.Common; 6 | using System.Data.SqlClient; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace Ivony.Data.SqlClient 13 | { 14 | 15 | 16 | /// 17 | /// SQL Server 数据库事务上下文对象 18 | /// 19 | public class SqlDbTransactionContext : DbTransactionContextBase 20 | { 21 | 22 | 23 | 24 | 25 | 26 | private IsolationLevel _isolationLevel; 27 | 28 | internal SqlDbTransactionContext( string connectionString, SqlDbConfiguration configuration, IsolationLevel isolationLevel ) 29 | { 30 | Connection = new SqlConnection( connectionString ); 31 | _executor = new SqlDbExecutorWithTransaction( this, configuration ); 32 | _isolationLevel = isolationLevel; 33 | } 34 | 35 | 36 | /// 37 | /// 获取数据库连接 38 | /// 39 | public SqlConnection Connection 40 | { 41 | get; 42 | private set; 43 | } 44 | 45 | 46 | 47 | /// 48 | /// 打开数据库连接并创建数据库事务对象。 49 | /// 50 | /// SQL Server 数据库事务对象 51 | protected override SqlTransaction CreateTransaction() 52 | { 53 | if ( Connection.State == ConnectionState.Closed ) 54 | Connection.Open(); 55 | 56 | return Connection.BeginTransaction( _isolationLevel ); 57 | } 58 | 59 | 60 | private SqlDbExecutorWithTransaction _executor; 61 | 62 | /// 63 | /// 获取用于在事务中执行查询的 SQL Server 查询执行器 64 | /// 65 | public override SqlDbExecutor DbExecutor 66 | { 67 | get { return _executor; } 68 | } 69 | 70 | 71 | 72 | private class SqlDbExecutorWithTransaction : SqlDbExecutor 73 | { 74 | public SqlDbExecutorWithTransaction( SqlDbTransactionContext transaction, SqlDbConfiguration configuration ) 75 | : base( transaction.Connection.ConnectionString, configuration ) 76 | { 77 | TransactionContext = transaction; 78 | } 79 | 80 | 81 | /// 82 | /// 当前所处的事务 83 | /// 84 | protected SqlDbTransactionContext TransactionContext 85 | { 86 | get; 87 | private set; 88 | } 89 | 90 | #if !NET40 91 | /// 92 | /// 重写 ExecuteAsync 方法,在事务中异步执行查询 93 | /// 94 | /// 要执行的查询命令 95 | /// 取消指示 96 | /// 用于追踪的追踪器 97 | /// 查询执行上下文 98 | protected sealed override async Task ExecuteAsync( SqlCommand command, CancellationToken token, IDbTracing tracing = null ) 99 | { 100 | try 101 | { 102 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 103 | 104 | command.Connection = TransactionContext.Connection; 105 | command.Transaction = TransactionContext.Transaction; 106 | 107 | if ( Configuration.QueryExecutingTimeout.HasValue ) 108 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 109 | 110 | 111 | var reader = await command.ExecuteReaderAsync( token ); 112 | var context = new SqlDbExecuteContext( TransactionContext, reader, tracing ); 113 | 114 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 115 | 116 | return context; 117 | } 118 | catch ( DbException exception ) 119 | { 120 | TryExecuteTracing( tracing, t => t.OnException( exception ) ); 121 | throw; 122 | } 123 | 124 | } 125 | #endif 126 | 127 | /// 128 | /// 执行查询命令并返回执行上下文 129 | /// 130 | /// 查询命令 131 | /// 用于追踪查询过程的追踪器 132 | /// 查询执行上下文 133 | protected sealed override IDbExecuteContext Execute( SqlCommand command, IDbTracing tracing = null ) 134 | { 135 | try 136 | { 137 | TryExecuteTracing( tracing, t => t.OnExecuting( command ) ); 138 | 139 | command.Connection = TransactionContext.Connection; 140 | command.Transaction = TransactionContext.Transaction; 141 | 142 | if ( Configuration.QueryExecutingTimeout.HasValue ) 143 | command.CommandTimeout = (int) Configuration.QueryExecutingTimeout.Value.TotalSeconds; 144 | 145 | 146 | var reader = command.ExecuteReader(); 147 | var context = new SqlDbExecuteContext( TransactionContext, reader, tracing ); 148 | 149 | TryExecuteTracing( tracing, t => t.OnLoadingData( context ) ); 150 | 151 | return context; 152 | } 153 | catch ( DbException exception ) 154 | { 155 | TryExecuteTracing( tracing, t => t.OnException( exception ) ); 156 | throw; 157 | } 158 | } 159 | 160 | 161 | } 162 | 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlClient/SqlParameterizedQueryParser.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data; 2 | using Ivony.Data.Common; 3 | using Ivony.Data.Queries; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Data; 7 | using System.Data.SqlClient; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | 13 | namespace Ivony.Data.SqlClient 14 | { 15 | 16 | /// 17 | /// 定义 SQL Server 的参数化查询解析器 18 | /// 19 | public class SqlParameterizedQueryParser : ParameterizedQueryParser 20 | { 21 | 22 | 23 | 24 | private class ParameterSpecification 25 | { 26 | public SqlDbType Type { get; set; } 27 | 28 | public int Size { get; set; } 29 | 30 | } 31 | 32 | 33 | private static Dictionary _parameterRules = new Dictionary(); 34 | 35 | private static object _sync = new object(); 36 | 37 | /// 38 | /// 注册一个参数规范 39 | /// 40 | /// 所适用的值类型 41 | /// 数据库参数类型 42 | /// 参数精度 43 | public static void RegisterParameterSpecification( Type valueType, SqlDbType type, int size = 0 ) 44 | { 45 | lock ( _sync ) 46 | { 47 | _parameterRules[valueType] = new ParameterSpecification { Type = type, Size = size }; 48 | } 49 | 50 | } 51 | 52 | 53 | /// 54 | /// 解除注册一个参数规范 55 | /// 56 | /// 所适用的值类型 57 | public static void UnregisterParameterSpecification( Type valueType ) 58 | { 59 | lock ( _sync ) 60 | { 61 | _parameterRules.Remove( valueType ); 62 | } 63 | } 64 | 65 | 66 | 67 | /// 68 | /// 创建参数并获取参数占位符 69 | /// 70 | /// 参数值 71 | /// 在模板中参数的位置顺序 72 | /// 创建的参数对象 73 | /// 参数占位符 74 | protected override string GetParameterPlaceholder( object value, int index, out SqlParameter parameter ) 75 | { 76 | var name = "@Param" + index; 77 | parameter = CreateParameter( name, value ); 78 | 79 | return name; 80 | } 81 | 82 | 83 | /// 84 | /// 创建参数对象 85 | /// 86 | /// 参数名 87 | /// 参数值 88 | /// 参数对象 89 | protected SqlParameter CreateParameter( string name, object value ) 90 | { 91 | if ( value != null ) 92 | { 93 | var valueType = value.GetType(); 94 | 95 | lock ( _sync ) 96 | { 97 | foreach ( var type in _parameterRules.Keys ) 98 | { 99 | if ( type.IsAssignableFrom( valueType ) ) 100 | { 101 | var rule = _parameterRules[type]; 102 | 103 | return new SqlParameter( name, rule.Type, rule.Size ) { Value = value }; 104 | } 105 | } 106 | } 107 | } 108 | 109 | return new SqlParameter( name, value ); 110 | } 111 | 112 | 113 | /// 114 | /// 创建 SqlCommand 对象 115 | /// 116 | /// 经过分析后的 SQL 查询文本 117 | /// 参数值列表 118 | /// 用于执行查询的 SqlCommand 对象 119 | protected override SqlCommand CreateCommand( string commandText, SqlParameter[] parameters ) 120 | { 121 | var command = new SqlCommand(); 122 | 123 | command.CommandText = commandText; 124 | command.Parameters.AddRange( parameters ); 125 | 126 | return command; 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlServer.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.SqlClient; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Configuration; 5 | using System.Data.SqlClient; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Ivony.Data.Common; 10 | using System.IO; 11 | 12 | namespace Ivony.Data 13 | { 14 | 15 | /// 16 | /// 提供 SQL Server 数据库访问支持 17 | /// 18 | public static class SqlServer 19 | { 20 | 21 | 22 | /// 23 | /// 从配置文件中读取连接字符串并创建 SQL Server 数据库访问器 24 | /// 25 | /// 连接字符串配置名称 26 | /// SQL Server 数据库配置 27 | /// SQL Server 数据库访问器 28 | public static SqlDbExecutor FromConfiguration( string name, SqlDbConfiguration configuration = null ) 29 | { 30 | var setting = ConfigurationManager.ConnectionStrings[name]; 31 | if ( setting == null ) 32 | throw new InvalidOperationException(); 33 | 34 | return Connect( setting.ConnectionString, configuration ); 35 | } 36 | 37 | 38 | /// 39 | /// 通过指定的连接字符串并创建 SQL Server 数据库访问器 40 | /// 41 | /// 连接字符串 42 | /// SQL Server 数据库配置 43 | /// SQL Server 数据库访问器 44 | public static SqlDbExecutor Connect( string connectionString, SqlDbConfiguration configuration = null ) 45 | { 46 | return new SqlDbExecutor( connectionString, configuration ?? Configuration ); 47 | } 48 | 49 | 50 | 51 | /// 52 | /// 通过指定的连接字符串构建器创建 SQL Server 数据库访问器 53 | /// 54 | /// 连接字符串构建器 55 | /// SQL Server 数据库配置 56 | /// SQL Server 数据库访问器 57 | public static SqlDbExecutor Connect( this SqlConnectionStringBuilder builder, SqlDbConfiguration configuration = null ) 58 | { 59 | return Connect( builder.ConnectionString, configuration ); 60 | } 61 | 62 | 63 | 64 | /// 65 | /// 通过指定的用户名和密码登陆 SQL Server 数据库,以创建 SQL Server 数据库访问器 66 | /// 67 | /// 数据库服务器实例名称 68 | /// 数据库名称 69 | /// 登录数据库的用户名 70 | /// 登录数据库的密码 71 | /// 是否启用连接池(默认启用) 72 | /// SQL Server 数据库配置 73 | /// SQL Server 数据库访问器 74 | public static SqlDbExecutor Connect( string dataSource, string initialCatalog, string userID, string password, bool pooling = true, SqlDbConfiguration configuration = null ) 75 | { 76 | var builder = new SqlConnectionStringBuilder() 77 | { 78 | DataSource = dataSource, 79 | InitialCatalog = initialCatalog, 80 | IntegratedSecurity = false, 81 | UserID = userID, 82 | Password = password, 83 | Pooling = pooling 84 | }; 85 | 86 | return Connect( builder.ConnectionString, configuration ); 87 | } 88 | 89 | 90 | /// 91 | /// 通过集成身份验证登陆 SQL Server 数据库,以创建 SQL Server 数据库访问器 92 | /// 93 | /// 数据库服务器实例名称 94 | /// 数据库名称 95 | /// 是否启用连接池(默认启用) 96 | /// SQL Server 数据库配置 97 | /// SQL Server 数据库访问器 98 | public static SqlDbExecutor Connect( string dataSource, string initialCatalog, bool pooling = true, SqlDbConfiguration configuration = null ) 99 | { 100 | var builder = new SqlConnectionStringBuilder() 101 | { 102 | DataSource = dataSource, 103 | InitialCatalog = initialCatalog, 104 | IntegratedSecurity = true, 105 | Pooling = pooling 106 | }; 107 | 108 | return Connect( builder.ConnectionString, configuration ); 109 | } 110 | 111 | 112 | 113 | 114 | 115 | 116 | private static SqlDbConfiguration _defaultConfiguration = new SqlDbConfiguration(); 117 | 118 | /// 119 | /// 获取或设置默认配置 120 | /// 121 | public static SqlDbConfiguration Configuration 122 | { 123 | get { return _defaultConfiguration; } 124 | } 125 | 126 | 127 | static SqlServer() 128 | { 129 | LocalDBInstanceName = "v11.0"; 130 | ExpressInstanceName = "SQLEXPRESS"; 131 | } 132 | 133 | 134 | internal static string LocalDBInstanceName { get; set; } 135 | 136 | internal static string ExpressInstanceName { get; set; } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlServerExpress.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.SqlClient; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data.SqlClient; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Ivony.Data 11 | { 12 | 13 | /// 14 | /// 提供 SQL Server Express 支持 15 | /// 16 | public static class SqlServerExpress 17 | { 18 | /// 19 | /// 通过连接 SQL Server Express LocalDB 实例,创建 SQL Server 数据库访问器 20 | /// 21 | /// 数据库名称或者数据库文件路径 22 | /// SQL Server 配置 23 | /// SQL Server 数据库访问器 24 | public static SqlDbExecutor ConnectLocalDB( string database, SqlDbConfiguration configuration = null ) 25 | { 26 | 27 | configuration = configuration ?? SqlServerExpress.Configuration; 28 | return Connect( database, @"(LocalDB)\" + configuration.LocalDBInstanceName, configuration ); 29 | 30 | } 31 | 32 | 33 | 34 | /// 35 | /// 通过连接 SQL Server Express 默认实例,创建 SQL Server 数据库访问器 36 | /// 37 | /// 数据库名称或者数据库文件路径 38 | /// SQL Server 配置 39 | /// SQL Server 数据库访问器 40 | public static SqlDbExecutor Connect( string database, SqlDbConfiguration configuration = null ) 41 | { 42 | configuration = configuration ?? SqlServerExpress.Configuration; 43 | return Connect( database, @"(local)\" + configuration.ExpressInstanceName, configuration ); 44 | } 45 | 46 | 47 | /// 48 | /// 通过连接 SQL Server Express 指定实例,创建 SQL Server 数据库访问器 49 | /// 50 | /// 数据库名称或者数据库文件路径 51 | /// SQL Server 实例名称 52 | /// SQL Server 配置 53 | /// SQL Server 数据库访问器 54 | private static SqlDbExecutor Connect( string database, string datasource, SqlDbConfiguration configuration = null ) 55 | { 56 | var builder = new SqlConnectionStringBuilder() 57 | { 58 | DataSource = datasource, 59 | IntegratedSecurity = true, 60 | }; 61 | 62 | 63 | if ( database.IndexOfAny( Path.GetInvalidPathChars() ) == -1 && Path.IsPathRooted( database ) ) 64 | builder.AttachDBFilename = database; 65 | 66 | else 67 | builder.InitialCatalog = database; 68 | 69 | 70 | return SqlServer.Connect( builder.ConnectionString, configuration ); 71 | } 72 | 73 | 74 | /// 75 | /// 获取或修改 SQL Server 默认配置 76 | /// 77 | public static SqlDbConfiguration Configuration 78 | { 79 | get { return SqlServer.Configuration; } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/SqlServerHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Ivony.Data 8 | { 9 | public static class SqlServerHelper 10 | { 11 | 12 | public IPagingDataSource MakePageSource( TemplateExpression expression, SqlDbUtility dbUtility ) 13 | { 14 | return new SqlServerPagingDataSource( expression, dbUtility ); 15 | } 16 | 17 | } 18 | 19 | public class SqlServerPagingDataSource : IPagingDataSource 20 | { 21 | private TemplateExpression _expression; 22 | private SqlDbUtility _dbUtility; 23 | 24 | public SqlServerPagingDataSource( TemplateExpression expression, SqlDbUtility dbUtility ) 25 | { 26 | _expression = expression; 27 | _dbUtility = dbUtility; 28 | } 29 | 30 | public IPagingData CreatePaging( int pageSize ) 31 | { 32 | return new Paging( _expression, _dbUtility, pageSize ); 33 | } 34 | 35 | private class Paging : IPagingData 36 | { 37 | private TemplateExpression _expression; 38 | private SqlDbUtility _dbUtility; 39 | 40 | public Paging( TemplateExpression expression, SqlDbUtility dbUtility, int pageSize ) 41 | { 42 | _expression = expression; 43 | _dbUtility = dbUtility; 44 | PageSize = pageSize; 45 | } 46 | 47 | public int PageSize 48 | { 49 | get; 50 | private set; 51 | 52 | } 53 | 54 | 55 | public int Count() 56 | { 57 | return _dbUtility.Scalar( "WITH( {0} ) AS DataSource SELECT COUNT(*) FROM DataSource" ); 58 | } 59 | 60 | 61 | public IEnumerable GetPage( int pageIndex ) 62 | { 63 | var expression = DbExpressions.Template( "WITH( {0} ) AS DataSource SELECT * , ROW_NUMBER() OVER " 64 | } 65 | 66 | System.Collections.IEnumerable IPagingData.GetPage( int pageIndex ) 67 | { 68 | return GetPage( pageIndex ); 69 | } 70 | 71 | } 72 | 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/TransactionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ivony.Data 9 | { 10 | 11 | /// 12 | /// 提供有关事务的一些扩展方法 13 | /// 14 | public static class TransactionExtensions 15 | { 16 | 17 | /// 18 | /// 创建并开启一个事务 19 | /// 20 | /// 数据库查询执行程序类型 21 | /// 数据库事务提供程序 22 | /// 数据库事务上下文 23 | public static IDbTransactionContext BeginTransaction( this IDbTransactionProvider provider ) 24 | { 25 | var transaction = provider.CreateTransaction(); 26 | transaction.BeginTransaction(); 27 | return transaction; 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/Ivony.Data/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Sources/PerformanceTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Sources/PerformanceTest/PerformanceTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EF894E7A-779D-483C-89F1-61541833DD34} 8 | Exe 9 | Properties 10 | PerformanceTest 11 | PerformanceTest 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {27d46d02-f7bc-42b2-ae3e-33eb5b1fa3f9} 54 | Ivony.Data 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /Sources/PerformanceTest/Program.cs: -------------------------------------------------------------------------------- 1 | using Ivony.Data; 2 | using Ivony.Data.SqlClient; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace PerformanceTest 11 | { 12 | class Program 13 | { 14 | 15 | 16 | static void Main( string[] args ) 17 | { 18 | 19 | var db = SqlServerExpress.Connect( "TestDatabase" ); 20 | 21 | db.T( "IF OBJECT_ID(N'[dbo].[Test1]') IS NOT NULL DROP TABLE [dbo].[Test1]" ).ExecuteNonQuery(); 22 | db.T( @" 23 | CREATE TABLE [dbo].[Test1] 24 | ( 25 | [ID] INT NOT NULL IDENTITY, 26 | [Name] NVARCHAR(50) NOT NULL , 27 | [Content] NTEXT NULL, 28 | [XmlContent] XML NULL, 29 | [Index] INT NOT NULL, 30 | CONSTRAINT [PK_Test1] PRIMARY KEY ([ID]) 31 | )" ).ExecuteNonQuery(); 32 | 33 | 34 | Test( db ); 35 | 36 | } 37 | 38 | private static void Test( SqlDbExecutor db ) 39 | { 40 | 41 | 42 | Stopwatch watch = new Stopwatch(); 43 | 44 | watch.Start(); 45 | 46 | for ( int i = 0; i < 10000; i++ ) 47 | db.T( "INSERT INTO Test1 ( Name, Content, XmlContent, [Index] ) VALUES ( {...} )", "Ivony", "Test", null, i ).ExecuteNonQuery(); 48 | 49 | db.T( "SELECT * FROM Test1" ).ExecuteDataTable(); 50 | 51 | watch.Stop(); 52 | 53 | Console.WriteLine( watch.Elapsed ); 54 | 55 | 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Sources/PerformanceTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle( "PerformanceTest" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "PerformanceTest" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2014" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible( false )] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid( "57f76f0b-a657-4829-9125-c4572cf4eb1c" )] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion( "1.0.0.0" )] 36 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 37 | -------------------------------------------------------------------------------- /Sources/UpgradeLog.htm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/UpgradeLog.htm -------------------------------------------------------------------------------- /Sources/packages/Ivony.Core.1.0.0/Ivony.Core.1.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Ivony.Core.1.0.0/Ivony.Core.1.0.0.nupkg -------------------------------------------------------------------------------- /Sources/packages/Ivony.Core.1.0.0/Ivony.Core.1.0.0.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ivony.Core 5 | 1.0.0 6 | Ivony.Core 7 | Ivony 8 | Ivony 9 | false 10 | core library for Ivony. 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Sources/packages/Ivony.Core.1.0.0/lib/Ivony.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Ivony.Core.1.0.0/lib/Ivony.Core.dll -------------------------------------------------------------------------------- /Sources/packages/Ivony.Logs.1.2/Ivony.Logs.1.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Ivony.Logs.1.2/Ivony.Logs.1.2.nupkg -------------------------------------------------------------------------------- /Sources/packages/Ivony.Logs.1.2/lib/net40/Ivony.Logs.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Ivony.Logs.1.2/lib/net40/Ivony.Logs.dll -------------------------------------------------------------------------------- /Sources/packages/MySql.Data.6.8.3/MySql.Data.6.8.3.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/MySql.Data.6.8.3/MySql.Data.6.8.3.nupkg -------------------------------------------------------------------------------- /Sources/packages/MySql.Data.6.8.3/lib/net20-cf/MySql.Data.cf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/MySql.Data.6.8.3/lib/net20-cf/MySql.Data.cf.dll -------------------------------------------------------------------------------- /Sources/packages/MySql.Data.6.8.3/lib/net20/MySql.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/MySql.Data.6.8.3/lib/net20/MySql.Data.dll -------------------------------------------------------------------------------- /Sources/packages/MySql.Data.6.8.3/lib/net40/MySql.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/MySql.Data.6.8.3/lib/net40/MySql.Data.dll -------------------------------------------------------------------------------- /Sources/packages/MySql.Data.6.8.3/lib/net45/MySql.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/MySql.Data.6.8.3/lib/net45/MySql.Data.dll -------------------------------------------------------------------------------- /Sources/packages/MySql.Data.6.8.3/lib/netcore45/MySql.Data.RT.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/MySql.Data.6.8.3/lib/netcore45/MySql.Data.RT.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/Npgsql.2.1.3.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/Npgsql.2.1.3.nupkg -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/Mono.Security.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/Mono.Security.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/Npgsql.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/Npgsql.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/de/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/de/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/es/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/es/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/fi/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/fi/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/fr/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/fr/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/ja/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/ja/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net20/zh-CN/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net20/zh-CN/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/Mono.Security.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/Mono.Security.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/Npgsql.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/Npgsql.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/de/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/de/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/es/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/es/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/fi/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/fi/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/fr/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/fr/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/ja/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/ja/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net35/zh-CN/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net35/zh-CN/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/Mono.Security.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/Mono.Security.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/Npgsql.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/Npgsql.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/de/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/de/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/es/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/es/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/fi/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/fi/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/fr/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/fr/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/ja/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/ja/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net40/zh-CN/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net40/zh-CN/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/Mono.Security.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/Mono.Security.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/Npgsql.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/Npgsql.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/de/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/de/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/es/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/es/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/fi/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/fi/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/fr/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/fr/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/ja/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/ja/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/Npgsql.2.1.3/lib/net45/zh-CN/Npgsql.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/Npgsql.2.1.3/lib/net45/zh-CN/Npgsql.resources.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/System.Data.SQLite.Core.1.0.92.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/System.Data.SQLite.Core.1.0.92.0.nupkg -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net20/x64/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net20/x64/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net20/x86/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net20/x86/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net40/x64/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net40/x64/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net40/x86/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net40/x86/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net45/x64/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net45/x64/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net45/x86/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net45/x86/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net451/x64/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net451/x64/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net451/x86/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/content/net451/x86/SQLite.Interop.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net20/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net20/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net40/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net40/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net45/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net45/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net451/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.1.0.92.0/lib/net451/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/tools/net20/install.ps1: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # install.ps1 -- 4 | # 5 | # Written by Joe Mistachkin. 6 | # Released to the public domain, use at your own risk! 7 | # 8 | ############################################################################### 9 | 10 | param($installPath, $toolsPath, $package, $project) 11 | 12 | $platformNames = "x86", "x64" 13 | $fileName = "SQLite.Interop.dll" 14 | $propertyName = "CopyToOutputDirectory" 15 | 16 | foreach($platformName in $platformNames) { 17 | $folder = $project.ProjectItems.Item($platformName) 18 | 19 | if ($folder -eq $null) { 20 | continue 21 | } 22 | 23 | $item = $folder.ProjectItems.Item($fileName) 24 | 25 | if ($item -eq $null) { 26 | continue 27 | } 28 | 29 | $property = $item.Properties.Item($propertyName) 30 | 31 | if ($property -eq $null) { 32 | continue 33 | } 34 | 35 | $property.Value = 1 36 | } 37 | -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/tools/net40/install.ps1: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # install.ps1 -- 4 | # 5 | # Written by Joe Mistachkin. 6 | # Released to the public domain, use at your own risk! 7 | # 8 | ############################################################################### 9 | 10 | param($installPath, $toolsPath, $package, $project) 11 | 12 | $platformNames = "x86", "x64" 13 | $fileName = "SQLite.Interop.dll" 14 | $propertyName = "CopyToOutputDirectory" 15 | 16 | foreach($platformName in $platformNames) { 17 | $folder = $project.ProjectItems.Item($platformName) 18 | 19 | if ($folder -eq $null) { 20 | continue 21 | } 22 | 23 | $item = $folder.ProjectItems.Item($fileName) 24 | 25 | if ($item -eq $null) { 26 | continue 27 | } 28 | 29 | $property = $item.Properties.Item($propertyName) 30 | 31 | if ($property -eq $null) { 32 | continue 33 | } 34 | 35 | $property.Value = 1 36 | } 37 | -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/tools/net45/install.ps1: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # install.ps1 -- 4 | # 5 | # Written by Joe Mistachkin. 6 | # Released to the public domain, use at your own risk! 7 | # 8 | ############################################################################### 9 | 10 | param($installPath, $toolsPath, $package, $project) 11 | 12 | $platformNames = "x86", "x64" 13 | $fileName = "SQLite.Interop.dll" 14 | $propertyName = "CopyToOutputDirectory" 15 | 16 | foreach($platformName in $platformNames) { 17 | $folder = $project.ProjectItems.Item($platformName) 18 | 19 | if ($folder -eq $null) { 20 | continue 21 | } 22 | 23 | $item = $folder.ProjectItems.Item($fileName) 24 | 25 | if ($item -eq $null) { 26 | continue 27 | } 28 | 29 | $property = $item.Properties.Item($propertyName) 30 | 31 | if ($property -eq $null) { 32 | continue 33 | } 34 | 35 | $property.Value = 1 36 | } 37 | -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.1.0.92.0/tools/net451/install.ps1: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # install.ps1 -- 4 | # 5 | # Written by Joe Mistachkin. 6 | # Released to the public domain, use at your own risk! 7 | # 8 | ############################################################################### 9 | 10 | param($installPath, $toolsPath, $package, $project) 11 | 12 | $platformNames = "x86", "x64" 13 | $fileName = "SQLite.Interop.dll" 14 | $propertyName = "CopyToOutputDirectory" 15 | 16 | foreach($platformName in $platformNames) { 17 | $folder = $project.ProjectItems.Item($platformName) 18 | 19 | if ($folder -eq $null) { 20 | continue 21 | } 22 | 23 | $item = $folder.ProjectItems.Item($fileName) 24 | 25 | if ($item -eq $null) { 26 | continue 27 | } 28 | 29 | $property = $item.Properties.Item($propertyName) 30 | 31 | if ($property -eq $null) { 32 | continue 33 | } 34 | 35 | $property.Value = 1 36 | } 37 | -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/System.Data.SQLite.Core.MSIL.1.0.92.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/System.Data.SQLite.Core.MSIL.1.0.92.0.nupkg -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net20/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net20/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net40/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net40/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net45/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net45/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net451/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivony/DbUtility/65620d56c43c0a819f1c0fcf70d6540882d1fc4c/Sources/packages/System.Data.SQLite.Core.MSIL.1.0.92.0/lib/net451/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Sources/packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------