├── .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