Project site - https://github.com/eeevgeniev/SQLEConnect
Table of contents
SQLEConnect is wrapper library for System.Data.Common.DbConnection
for parsing SQL query results to supported by the library .NET types.
using Connection<NpgsqlConnection> connection = new Connection<NpgsqlConnection>(connectionString, useTransaction, isolationLevel, timeout);
List<Model> models = connection.Query<Model>(commandText, new List<SqlEParameter>() { new SqlEParameter("@id", 1) }, isStoredProcedure, prepareCommand);
Where:
connectionString
is SQL connection string;useTransaction
isboolean
value, which by default isfalse
. Iftrue
theConnection
instance will wrap all queries in transaction. This transaction can be completed either by callingCommitTransaction
of theConnection
instance or when this instance is disposed by theDispose
method;isolationLevel
- the transaction isolation level, by default isnull
;timeout
- theCommandTimeout
, by default isnull
and it will use the default value ofCommandTimeout
property ofDbCommand
instance;- commandText for example "SELECT * FROM models WHERE id = @id;" is the query command or stored procedure name if
isStoredProcedure
istrue
; - SQL parameters of type
IEnumerable<SqlEParameter>
ornull
; isStoredProcedure
isboolean
value which is by defaultfalse
. If set totrue
theConnection
Query
method will use stored procedure;prepareCommand
isboolean
value, which is by defaultfalse
. Used to prepare the command if possible;
using Connection<SqlConnection> connection = new Connection<SqlConnection>(connectionString);
var (hasResult, value) = connection.Single<int>("SELECT TOP 1 number FROM table;", null);
Where:
hasResult
isboolean
and it istrue
if there is a result;value
- the actual value, in the example it is of typeint
. IfhasResult
is false thevalue
will be the default value for the type;
using Connection<SqliteConnection> connection = new Connection<SqliteConnection>(connectionString);
int deleted = await connection.NonQueryAsync("DELETE FROM table WHERE id < @id;", new List<SqlEParameter>() { new SqlEParameter("@id", 4) });
Where the result is normally the count of the affected fields.
using Connection<MySqlConnection> connection = new Connection<MySqlConnection>(connectionString);
List<Model> models = connection.Query<Model>("SELECT * FROM models WHERE id < @id;", new List<SqlEParameter>() { new SqlEParameter("@id", 11) });
List<int> numbers = connection.Query<int>("SELECT id FROM models WHERE id < @id;", new List<SqlEParameter>() { new SqlEParameter("@id", 21) });
using Connection<OracleConnection> connection = new Connection<OracleConnection>(connectionString);
var (models, numbers) = await connection.QueryMultipleAsync<Model, int>(
"SELECT * FROM models WHERE id < @id; SELECT id FROM models WHERE id < @id;",
new List<SqlEParameter>() { new SqlEParameter("@id", 1) })
Where
models
is of typeList<Model>
andnumbers
is of typeList<int>
Note currently up to 10 results are supported.
Note every mehtod has alternative async method with the same name and postfix 'Async'.
Instance method:
using Connection<SqliteConnection> connection = new Connection<SqliteConnection>(connectionString);
connection.AddOrUpdate(new ModelParser());
Static method
Connection<SqliteConnection>.AddOrUpdateParser(new ModelParser());
Where the parser must implement interface SQLEConnect.Interfaces.IParser<TModel>
. With the following structure:
// for multiple results
IEnumerable<TModel> Parse(DbDataReader dbDataReader);
// for single result
(bool hasResult, TModel result) ParseSingle(DbDataReader dbDataReader);
Type Type();
Note The parsers are stored in static container to be used by all instances.
Support for dynamic
and object
with System.Dynamic.ExpandoObject
.
using Connection<NpgsqlConnection> connection = new Connection<NpgsqlConnection>(connectionString);
var models = connection.Query<dynamic>("SELECT * FROM models;", null);
using Connection<NpgsqlConnection> connection = new Connection<NpgsqlConnection>(connectionString);
var objects = connection.Query<object>("SELECT * FROM models;", null);
Note if you want to access List you must cast it to System.Dynamic.ExpandoObject
or dynamic
.
For single query
(bool hasResult, dynamic result) x = connection.Single<dynamic>("SELECT * FROM models ORDER BY id LIMIT 1;", null);
Instance method:
using Connection<SqlConnection> connection = new Connection<SqlConnection>(connectionString);
connection.ClearParsers();
Static method:
Connection<SqliteConnection>.ClearAllParsers();
Currently the supported types are:
- String - with
DbDataReader.GetString
; - Char - with DbDataReader.GetString(). Note the result is received from
GetString
method, it must beNull
or white space or string with length of 1 otherwise anInvalidOperationException
is throw; - Char? - with DbDataReader.GetString() Note the result is received from
GetString
, it must beNull
or white space or string with length of 1 otherwise anInvalidOperationException
is throw; - Byte - with
DbDataReader.GetByte
; - Byte? - with
DbDataReader.GetByte
; - SByte - with
DbDataReader.GetValue
. Note Converted withConvert.ToSByte
; - SByte? - with
DbDataReader.GetValue
. Note Converted withConvert.ToSByte
; - Short - with
DbDataReader.GetInt16
; - Short? - with
DbDataReader.GetInt16
; - UShort - with
DbDataReader.GetValue
. Note Converted withConvert.ToUInt16
; - UShort? - with
DbDataReader.GetValue
. Note Converted withConvert.ToUInt16
; - Int - with
DbDataReader.GetInt32
; - Int? - with
DbDataReader.GetInt32
; - UInt - with
DbDataReader.GetValue
. Note Converted withConvert.ToUInt32
; - UInt? - with
DbDataReader.GetValue
. Note Converted withConvert.ToUInt32
; - Long - with
DbDataReader.GetInt64
; - Long? - with
DbDataReader.GetInt64
; - ULong - with
DbDataReader.GetValue
. Note Converted withConvert.ToUInt64
; - ULong? - with
DbDataReader.GetValue
. Note Converted withConvert.ToUInt64
; - Float - with
DbDataReader.GetFloat
; - Float? - with
DbDataReader.GetFloat
; - Double - with
DbDataReader.GetDouble
; - Double? - with
DbDataReader.GetDouble
; - Decimal - with
DbDataReader.GetDecimal
; - Decimal? - with
DbDataReader.GetDecimal
; - DateTime - with
DbDataReader.GetDateTime
; - DateTime? - with
DbDataReader.GetDateTime
; - Boolean - with
DbDataReader.GetBoolean
; - Boolean? - with
DbDataReader.GetBoolean
; - Guid - with
DbDataReader.GetGuid
; - Guid? - with
DbDataReader.GetGuid
; - Byte[] - with
DbDataReader.GetBytes
; - Char[] - with
DbDataReader.GetChars
; - Stream - with
DbDataReader.GetStream
. Note the result is stored inMemoryStream
; - Custom classes - custom classes/models;
- Custom structs - custom classes/models;
- Dictionary<string, object> - generic result;
- Object and dynamic with
System.Dynamic.ExpandoObject
For all types except Object
, Struct
and Dictionary<string, object>
the first selected column from the SQL query must be from compatible type. Only the first column is checked.
For example:
List<int> numbers = connection.Query<int>("SELECT Id, Name FROM models;", null)
Id
column must be compatible with Integer
type. The Name
column is never checked.
The Dictionary<string, object>
is used when there is no need to save the results in specific model. The results are parsed based on the DbDataReader
-> GetFieldType
method.
Example:
using Connection<NpgsqlConnection> connection = new Connection<NpgsqlConnection>(connectionString, useTransaction, isolationLevel, timeout);
List<Dictionary<string, object>> models = connection.Query<Dictionary<string, object>>("SELECT * FROM models WHERE id = @id;", new List<SqlEParameter>() { new SqlEParameter("@id", 1) });
For every record in the DbDataReader
a new Dictionary<string, object>
is created where the key is the column name and the value is the row value of the DbDataReader
.
Object
and Struct
results are parsed based on either their public type properties or public type fields. First are checked the public properties if there are no public properties then are checked the public fields. When the instance of class or struct is created, it is used the constructor with least parameters. This constructor must accept default values for parameters.
The solution contains 3 projects:
SQLEConnect
- main project;SQLEConnectTests
- project with test against databases;SQLEConnectUnitTests
- project with unit tests;
EConnect
contains:
- Directory
Infrastructure
- contains various helpers; - Directory
Interfaces
- contains variousInterfaces
; - Directory
ParserFactories
- contains the main class for creating parsers; - Directory
Parsers
- contains all classes for parsing; - Class
Connection
- main class used by the library; - Class
SqlEParameter
- main class for using SQL parameters;
SQLEConnectTests
contains:
SQLEConnectTests.Benchmarks
project - used to run benchmarks in eitherDevelop
environment orRelease
environment. InRelease
environment the test are run withBenchmarkDotNet
library;SQLEConnectTests.Models
project - with some model-classes used by the other projects;SQLEConnectTests.MySQLQueries
project - with tests for MySQL;SQLEConnectTests.OracleDatabaseQueries
project - with tesst for Oracle;SQLEConnectTests.PostgreSQLQueries
project - with tests for PostgreSQL;SQLEConnectTests.SettingParser
project - for readingsettings.json
;SQLEConnectTests.Settings
project -settings.json
model;SQLEConnectTests.SQLiteQueries
project - with tests for SQLite;SQLEConnectTests.SQLServerQueries
project - with tests for SQLServer;
Note every project has settings.json
with property ConnectionString
where the connection string must be entered. It's empty by default.
SQLEConnectUnitTests
contains:
Projects with unit tests which are organized by type. For example: QueryBoolTests
contains tests for Boolean
and Boolean?
types and all queries. And SingleBoolTests
contains tests for Boolean
and Boolean?
but only for single queries. There are some helper directories like:
Mockups
for some mockups;TestModels
for some tests models;
Because this library is wrapper for System.Data.Common.DbConnection
it depends on different implementations of DbDataReader
, for example: SQL Server (SqlConnection
) or SQLite (SqliteConnection
). This may lead to some methods to be not implemented, for example: the GetChar
, or GetGuid
methods. It's possible if you change the SQL provider some models to not work.