From f05541cf6833cfafdccf5326721bdc886927c2e8 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Tue, 10 Jun 2025 23:36:18 +0300 Subject: [PATCH 01/11] WIP - test with transactions --- .../MySqlConnectorDapperTester.generated.cs | 28 ++++++- .../MySqlConnectorDapperExample/QuerySql.cs | 77 ++++++++++++++----- 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index a9de91c1..c9396617 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -1,8 +1,10 @@ +using MySqlConnector; using MySqlConnectorDapperExampleGen; using NUnit.Framework; using NUnit.Framework.Legacy; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -26,6 +28,30 @@ public async Task TestOne() Assert.That(SingularEquals(expected, actual)); } + [Test] + public async Task TestTransactionOne() + { + var connection = new MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); + await transaction.CommitAsync(); + + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); + } + private static bool SingularEquals(QuerySql.GetAuthorRow x, QuerySql.GetAuthorRow y) { return x.Id.Equals(y.Id) && x.Name.Equals(y.Name) && x.Bio.Equals(y.Bio); @@ -625,4 +651,4 @@ public async Task TestCopyFrom(int batchSize, MysqlTypesCEnum? cEnum) Assert.That(actual.CEnum, Is.EqualTo(expected.CEnum)); } } -} +} diff --git a/examples/MySqlConnectorDapperExample/QuerySql.cs b/examples/MySqlConnectorDapperExample/QuerySql.cs index af71692a..6c99b222 100644 --- a/examples/MySqlConnectorDapperExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperExample/QuerySql.cs @@ -1,9 +1,9 @@ -// auto-generated by sqlc - do not edit -// ReSharper disable UseObjectOrCollectionInitializer -// ReSharper disable UseAwaitUsing -// ReSharper disable ConvertToUsingDeclaration -// ReSharper disable NotAccessedPositionalProperty.Global -// ReSharper disable UnusedAutoPropertyAccessor.Global +// auto-generated by sqlc - do not edit +// ReSharper disable UseObjectOrCollectionInitializer +// ReSharper disable UseAwaitUsing +// ReSharper disable ConvertToUsingDeclaration +// ReSharper disable NotAccessedPositionalProperty.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -19,13 +19,24 @@ namespace MySqlConnectorDapperExampleGen; public class QuerySql { - public QuerySql(string connectionString) + public QuerySql() { - this.ConnectionString = connectionString; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - private string ConnectionString { get; } + public QuerySql(string connectionString) : this() + { + this.ConnectionString = connectionString; + } + + public QuerySql(MySqlTransaction transaction) : this() + { + this.mySqlTransaction = transaction; + } + + private MySqlTransaction? mySqlTransaction { get; } + + private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1; SELECT LAST_INSERT_ID()"; public class GetAuthorRow @@ -40,13 +51,26 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.mySqlTransaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); - return result; + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); + return result; + } + } + + if (this.mySqlTransaction?.Connection == null || this.mySqlTransaction?.Connection.State != System.Data.ConnectionState.Open) { + throw new InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await mySqlTransaction.Connection.QueryFirstOrDefaultAsync( + GetAuthorSql, + queryParams, + transaction: this.mySqlTransaction); + } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name; SELECT LAST_INSERT_ID()"; @@ -74,14 +98,27 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.mySqlTransaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - await connection.ExecuteAsync(CreateAuthorSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(CreateAuthorSql, queryParams); + } + } + + if (this.mySqlTransaction?.Connection == null || this.mySqlTransaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new InvalidOperationException("Transaction is provided, but its connection is null."); } + + await mySqlTransaction.Connection.ExecuteAsync( + CreateAuthorSql, + queryParams, + transaction: this.mySqlTransaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio); SELECT LAST_INSERT_ID()"; From 9e063651187faa70bd2b40f3475c968b191b3814 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 09:43:17 +0300 Subject: [PATCH 02/11] working transaction generation still needs tests and docs --- CodeGenerator/Generators/QueriesGen.cs | 9 +- Drivers/DbDriver.cs | 12 + Drivers/Generators/ExecDeclareGen.cs | 121 +- Drivers/Generators/ExecLastIdDeclareGen.cs | 119 +- Drivers/Generators/ExecRowsDeclareGen.cs | 116 +- Drivers/Generators/ManyDeclareGen.cs | 136 +- Drivers/Generators/OneDeclareGen.cs | 158 ++- Drivers/MySqlConnectorDriver.cs | 2 + Drivers/NpgsqlDriver.cs | 9 + Drivers/SqliteDriver.cs | 2 + Drivers/Variable.cs | 1 + .../MySqlConnectorDapperTester.generated.cs | 28 +- .../MySqlConnectorDapperExample/QuerySql.cs | 585 ++++++--- .../QuerySql.cs | 578 +++++--- examples/MySqlConnectorExample/QuerySql.cs | 1166 +++++++++++++---- .../MySqlConnectorLegacyExample/QuerySql.cs | 1164 ++++++++++++---- examples/NpgsqlDapperExample/QuerySql.cs | 537 ++++++-- .../NpgsqlDapperLegacyExample/QuerySql.cs | 535 ++++++-- examples/NpgsqlExample/QuerySql.cs | 1010 +++++++++++--- examples/NpgsqlLegacyExample/QuerySql.cs | 1008 +++++++++++--- examples/SqliteDapperExample/QuerySql.cs | 458 +++++-- .../SqliteDapperLegacyExample/QuerySql.cs | 456 +++++-- examples/SqliteExample/QuerySql.cs | 768 ++++++++--- examples/SqliteLegacyExample/QuerySql.cs | 766 ++++++++--- 24 files changed, 7443 insertions(+), 2301 deletions(-) diff --git a/CodeGenerator/Generators/QueriesGen.cs b/CodeGenerator/Generators/QueriesGen.cs index 84efcb2a..89ca1dc4 100644 --- a/CodeGenerator/Generators/QueriesGen.cs +++ b/CodeGenerator/Generators/QueriesGen.cs @@ -64,7 +64,14 @@ public class {{className}} { {{dbDriver.GetConstructorStatements().JoinByNewLine()}} } - private string {{Variable.ConnectionString.AsPropertyName()}} { get; } + + public {{className}}({{dbDriver.TransactionClassName}} {{Variable.Transaction.AsVarName()}}) + { + {{dbDriver.GetTransactionConstructorStatements().JoinByNewLine()}} + } + + private {{dbDriver.AddNullableSuffixIfNeeded(dbDriver.TransactionClassName, false)}} {{Variable.Transaction.AsPropertyName()}} { get; } + private {{dbDriver.AddNullableSuffixIfNeeded("string", false)}} {{Variable.ConnectionString.AsPropertyName()}} { get; } } """)!; return classDeclaration.AddMembers(classMembers.ToArray()); diff --git a/Drivers/DbDriver.cs b/Drivers/DbDriver.cs index 38539f96..bcb470d7 100644 --- a/Drivers/DbDriver.cs +++ b/Drivers/DbDriver.cs @@ -15,6 +15,8 @@ public abstract class DbDriver public string DefaultSchema { get; } + public abstract string TransactionClassName { get; } + public Dictionary> Tables { get; } public Dictionary> Enums { get; } @@ -118,6 +120,16 @@ public virtual string[] GetConstructorStatements() .ToArray(); } + public virtual string[] GetTransactionConstructorStatements() + { + return new List + { + $"this.{Variable.Transaction.AsPropertyName()} = {Variable.Transaction.AsVarName()};" + } + .AppendIf("Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;", Options.UseDapper) + .ToArray(); + } + public virtual MemberDeclarationSyntax[] GetMemberDeclarationsForUtils() { return []; diff --git a/Drivers/Generators/ExecDeclareGen.cs b/Drivers/Generators/ExecDeclareGen.cs index a5c64940..bc061e3b 100644 --- a/Drivers/Generators/ExecDeclareGen.cs +++ b/Drivers/Generators/ExecDeclareGen.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Plugin; +using System.Linq; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace SqlcGenCsharp.Drivers.Generators; @@ -21,40 +22,94 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte private string GetMethodBody(string queryTextConstant, Query query) { - var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); var sqlTextTransform = CommonGen.GetSqlTransformations(query, queryTextConstant); - return dbDriver.Options.UseDapper ? GetAsDapper() : GetAsDriver(); - - string GetAsDapper() - { - var dapperParamsSection = CommonGen.ConstructDapperParamsDict(query.Params); - var dapperArgs = dapperParamsSection != string.Empty - ? $", {Variable.QueryParams.AsVarName()}" - : string.Empty; - return $$""" - using ({{establishConnection}}) - {{{sqlTextTransform}}{{dapperParamsSection}} - await {{Variable.Connection.AsVarName()}}.ExecuteAsync({{queryTextConstant}}{{dapperArgs}}); + var useDapper = dbDriver.Options.UseDapper; + + var dapperParams = useDapper ? CommonGen.ConstructDapperParamsDict(query.Params) : string.Empty; + var sqlVar = sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant; + var transactionProperty = Variable.Transaction.AsPropertyName(); + + var noTxBody = useDapper ? GetDapperNoTxBody(sqlVar, query) : GetDriverNoTxBody(sqlVar, query); + var withTxBody = useDapper ? GetDapperWithTxBody(sqlVar, query) : GetDriverWithTxBody(sqlVar, query); + + return $$""" + {{sqlTextTransform}} + {{dapperParams}} + if (this.{{transactionProperty}} == null) + { + {{noTxBody}} + } + {{withTxBody}} + """; + } + + private string GetDapperNoTxBody(string sqlVar, Query query) + { + var (establishConnection, _) = dbDriver.EstablishConnection(query); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + return $$""" + using ({{establishConnection}}) + { + await {{Variable.Connection.AsVarName()}}.ExecuteAsync({{sqlVar}}{{dapperArgs}}); + } + return; + """; + } + + private string GetDapperWithTxBody(string sqlVar, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.{{transactionProperty}}.Connection.ExecuteAsync( + {{sqlVar}}{{dapperArgs}}, + transaction: this.{{transactionProperty}}); + """; + } + + private string GetDriverNoTxBody(string sqlVar, Query query) + { + var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); + var createSqlCommand = dbDriver.CreateSqlCommand(sqlVar); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + return $$""" + using ({{establishConnection}}) + { + {{connectionOpen.AppendSemicolonUnlessEmpty()}} + using ({{createSqlCommand}}) + { + {{commandParameters}} + await {{Variable.Command.AsVarName()}}.ExecuteNonQueryAsync(); } - """; - } - - string GetAsDriver() - { - var commandParameters = CommonGen.AddParametersToCommand(query.Params); - var createSqlCommand = dbDriver.CreateSqlCommand(sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant); - var executeScalar = $"await {Variable.Command.AsVarName()}.ExecuteScalarAsync();"; - return $$""" - using ({{establishConnection}}) - { - {{connectionOpen.AppendSemicolonUnlessEmpty()}}{{sqlTextTransform}} - using ({{createSqlCommand}}) - { - {{commandParameters}} - {{executeScalar}} - } - } - """; - } + } + return; + """; + } + + private string GetDriverWithTxBody(string sqlVar, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var commandVar = Variable.Command.AsVarName(); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var {{commandVar}} = this.{{transactionProperty}}.Connection.CreateCommand()) + { + {{commandVar}}.CommandText = {{sqlVar}}; + {{commandVar}}.Transaction = this.{{transactionProperty}}; + {{commandParameters}} + await {{commandVar}}.ExecuteNonQueryAsync(); + } + """; } } \ No newline at end of file diff --git a/Drivers/Generators/ExecLastIdDeclareGen.cs b/Drivers/Generators/ExecLastIdDeclareGen.cs index de46f6db..b00964e4 100644 --- a/Drivers/Generators/ExecLastIdDeclareGen.cs +++ b/Drivers/Generators/ExecLastIdDeclareGen.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Plugin; +using System.Linq; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace SqlcGenCsharp.Drivers.Generators; @@ -21,42 +22,92 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte private string GetMethodBody(string queryTextConstant, Query query) { - var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); var sqlTextTransform = CommonGen.GetSqlTransformations(query, queryTextConstant); - connectionOpen = connectionOpen.AppendSemicolonUnlessEmpty(); - return dbDriver.Options.UseDapper ? GetAsDapper() : GetAsDriver(); - - string GetAsDapper() - { - var dapperParamsSection = CommonGen.ConstructDapperParamsDict(query.Params); - var dapperArgs = dapperParamsSection == string.Empty - ? string.Empty - : $", {Variable.QueryParams.AsVarName()}"; - return $$""" - using ({{establishConnection}}) - {{{sqlTextTransform}}{{dapperParamsSection}} - return await {{Variable.Connection.AsVarName()}}.QuerySingleAsync<{{dbDriver.GetIdColumnType(query)}}>({{queryTextConstant}}{{dapperArgs}}); - } - """; - } - - string GetAsDriver() - { - var sqlTextVar = sqlTextTransform == string.Empty ? queryTextConstant : Variable.TransformedSql.AsVarName(); - var createSqlCommand = dbDriver.CreateSqlCommand(sqlTextVar); - var commandParameters = CommonGen.AddParametersToCommand(query.Params); - var returnLastId = ((IExecLastId)dbDriver).GetLastIdStatement(query).JoinByNewLine(); - return $$""" - using ({{establishConnection}}) - { - {{connectionOpen}}{{sqlTextTransform}} - using ({{createSqlCommand}}) - { + var useDapper = dbDriver.Options.UseDapper; + + var dapperParams = useDapper ? CommonGen.ConstructDapperParamsDict(query.Params) : string.Empty; + var sqlVar = sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant; + var transactionProperty = Variable.Transaction.AsPropertyName(); + + var noTxBody = useDapper ? GetDapperNoTxBody(sqlVar, query) : GetDriverNoTxBody(sqlVar, query); + var withTxBody = useDapper ? GetDapperWithTxBody(sqlVar, query) : GetDriverWithTxBody(sqlVar, query); + + return $$""" + {{sqlTextTransform}} + {{dapperParams}} + if (this.{{transactionProperty}} == null) + { + {{noTxBody}} + } + {{withTxBody}} + """; + } + + private string GetDapperNoTxBody(string sqlVar, Query query) + { + var (establishConnection, _) = dbDriver.EstablishConnection(query); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + return $$""" + using ({{establishConnection}}) + { + return await {{Variable.Connection.AsVarName()}}.QuerySingleAsync<{{dbDriver.GetIdColumnType(query)}}>({{sqlVar}}{{dapperArgs}}); + } + """; + } + + private string GetDapperWithTxBody(string sqlVar, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.{{transactionProperty}}.Connection.QuerySingleAsync<{{dbDriver.GetIdColumnType(query)}}>({{sqlVar}}{{dapperArgs}}, transaction: this.{{transactionProperty}}); + """; + } + + private string GetDriverNoTxBody(string sqlVar, Query query) + { + var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); + var createSqlCommand = dbDriver.CreateSqlCommand(sqlVar); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + var returnLastId = ((IExecLastId)dbDriver).GetLastIdStatement(query).JoinByNewLine(); + return $$""" + using ({{establishConnection}}) + { + {{connectionOpen.AppendSemicolonUnlessEmpty()}} + using ({{createSqlCommand}}) + { {{commandParameters}} {{returnLastId}} - } - } - """; - } + } + } + """; + } + + private string GetDriverWithTxBody(string sqlVar, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var commandVar = Variable.Command.AsVarName(); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + var returnLastId = ((IExecLastId)dbDriver).GetLastIdStatement(query).JoinByNewLine(); + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var {{commandVar}} = this.{{transactionProperty}}.Connection.CreateCommand()) + { + {{commandVar}}.CommandText = {{sqlVar}}; + {{commandVar}}.Transaction = this.{{transactionProperty}}; + {{commandParameters}} + {{returnLastId}} + } + """; } } \ No newline at end of file diff --git a/Drivers/Generators/ExecRowsDeclareGen.cs b/Drivers/Generators/ExecRowsDeclareGen.cs index b8ca1952..ec6806f7 100644 --- a/Drivers/Generators/ExecRowsDeclareGen.cs +++ b/Drivers/Generators/ExecRowsDeclareGen.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Plugin; +using System.Linq; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace SqlcGenCsharp.Drivers.Generators; @@ -21,39 +22,92 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte private string GetMethodBody(string queryTextConstant, Query query) { - var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); var sqlTextTransform = CommonGen.GetSqlTransformations(query, queryTextConstant); - return dbDriver.Options.UseDapper ? GetAsDapper() : GetAsDriver(); - - string GetAsDapper() - { - var dapperParamsSection = CommonGen.ConstructDapperParamsDict(query.Params); - var dapperArgs = dapperParamsSection != string.Empty ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; - return $$""" - using ({{establishConnection}}) - {{{sqlTextTransform}}{{dapperParamsSection}} - return await {{Variable.Connection.AsVarName()}}.ExecuteAsync({{queryTextConstant}}{{dapperArgs}}); - } - """; - } - - string GetAsDriver() - { - var createSqlCommand = dbDriver.CreateSqlCommand(sqlTextTransform != string.Empty - ? Variable.TransformedSql.AsVarName() - : queryTextConstant); - var commandParameters = CommonGen.AddParametersToCommand(query.Params); - return $$""" - using ({{establishConnection}}) - { - {{connectionOpen.AppendSemicolonUnlessEmpty()}}{{sqlTextTransform}} - using ({{createSqlCommand}}) - { + var useDapper = dbDriver.Options.UseDapper; + + var dapperParams = useDapper ? CommonGen.ConstructDapperParamsDict(query.Params) : string.Empty; + var sqlVar = sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant; + var transactionProperty = Variable.Transaction.AsPropertyName(); + + var noTxBody = useDapper ? GetDapperNoTxBody(sqlVar, query) : GetDriverNoTxBody(sqlVar, query); + var withTxBody = useDapper ? GetDapperWithTxBody(sqlVar, query) : GetDriverWithTxBody(sqlVar, query); + + return $$""" + {{sqlTextTransform}} + {{dapperParams}} + if (this.{{transactionProperty}} == null) + { + {{noTxBody}} + } + {{withTxBody}} + """; + } + + private string GetDapperNoTxBody(string sqlVar, Query query) + { + var (establishConnection, _) = dbDriver.EstablishConnection(query); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + return $$""" + using ({{establishConnection}}) + { + return await {{Variable.Connection.AsVarName()}}.ExecuteAsync({{sqlVar}}{{dapperArgs}}); + } + """; + } + + private string GetDapperWithTxBody(string sqlVar, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.{{transactionProperty}}.Connection.ExecuteAsync( + {{sqlVar}}{{dapperArgs}}, + transaction: this.{{transactionProperty}}); + """; + } + + private string GetDriverNoTxBody(string sqlVar, Query query) + { + var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); + var createSqlCommand = dbDriver.CreateSqlCommand(sqlVar); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + return $$""" + using ({{establishConnection}}) + { + {{connectionOpen.AppendSemicolonUnlessEmpty()}} + using ({{createSqlCommand}}) + { {{commandParameters}} return await {{Variable.Command.AsVarName()}}.ExecuteNonQueryAsync(); - } - } - """; - } + } + } + """; + } + + private string GetDriverWithTxBody(string sqlVar, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var commandVar = Variable.Command.AsVarName(); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var {{commandVar}} = this.{{transactionProperty}}.Connection.CreateCommand()) + { + {{commandVar}}.CommandText = {{sqlVar}}; + {{commandVar}}.Transaction = this.{{transactionProperty}}; + {{commandParameters}} + return await {{commandVar}}.ExecuteNonQueryAsync(); + } + """; } } \ No newline at end of file diff --git a/Drivers/Generators/ManyDeclareGen.cs b/Drivers/Generators/ManyDeclareGen.cs index 61484bbd..429371bd 100644 --- a/Drivers/Generators/ManyDeclareGen.cs +++ b/Drivers/Generators/ManyDeclareGen.cs @@ -24,47 +24,81 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte private string GetMethodBody(string queryTextConstant, string returnInterface, Query query) { - var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); var sqlTextTransform = CommonGen.GetSqlTransformations(query, queryTextConstant); - var resultVar = Variable.Result.AsVarName(); var anyEmbeddedTableExists = query.Columns.Any(c => c.EmbedTable is not null); - return dbDriver.Options.UseDapper && !anyEmbeddedTableExists - ? GetAsDapper() - : GetAsDriver(); - - string GetAsDapper() - { - var dapperParamsSection = CommonGen.ConstructDapperParamsDict(query.Params); - var dapperArgs = dapperParamsSection != string.Empty ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; - var returnType = dbDriver.AddNullableSuffixIfNeeded(returnInterface, true); - var sqlQuery = sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant; - - return $$""" - using ({{establishConnection}}) - {{{sqlTextTransform}}{{dapperParamsSection}} - var {{resultVar}} = await {{Variable.Connection.AsVarName()}}.QueryAsync<{{returnType}}>({{sqlQuery}}{{dapperArgs}}); - return {{resultVar}}.AsList(); - } - """; - } - - string GetAsDriver() - { - var createSqlCommand = dbDriver.CreateSqlCommand(sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant); - var commandParameters = CommonGen.AddParametersToCommand(query.Params); - var initDataReader = CommonGen.InitDataReader(); - var awaitReaderRow = CommonGen.AwaitReaderRow(); - var dataclassInit = CommonGen.InstantiateDataclass(query.Columns.ToArray(), returnInterface); - var readWhileExists = $$""" + var useDapper = dbDriver.Options.UseDapper && !anyEmbeddedTableExists; + + var dapperParams = useDapper ? CommonGen.ConstructDapperParamsDict(query.Params) : string.Empty; + var sqlVar = sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant; + var transactionProperty = Variable.Transaction.AsPropertyName(); + + var noTxBody = useDapper ? GetDapperNoTxBody(sqlVar, returnInterface, query) : GetDriverNoTxBody(sqlVar, returnInterface, query); + var withTxBody = useDapper ? GetDapperWithTxBody(sqlVar, returnInterface, query) : GetDriverWithTxBody(sqlVar, returnInterface, query); + + return $$""" + {{sqlTextTransform}} + {{dapperParams}} + if (this.{{transactionProperty}} == null) + { + {{noTxBody}} + } + {{withTxBody}} + """; + } + + private string GetDapperNoTxBody(string sqlVar, string returnInterface, Query query) + { + var (establishConnection, _) = dbDriver.EstablishConnection(query); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + var returnType = dbDriver.AddNullableSuffixIfNeeded(returnInterface, true); + + return $$""" + using ({{establishConnection}}) + { + var {{Variable.Result.AsVarName()}} = await {{Variable.Connection.AsVarName()}}.QueryAsync<{{returnType}}>({{sqlVar}}{{dapperArgs}}); + return {{Variable.Result.AsVarName()}}.AsList(); + } + """; + } + + private string GetDapperWithTxBody(string sqlVar, string returnInterface, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + var returnType = dbDriver.AddNullableSuffixIfNeeded(returnInterface, true); + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return (await this.{{transactionProperty}}.Connection.QueryAsync<{{returnType}}>( + {{sqlVar}}{{dapperArgs}}, + transaction: this.{{transactionProperty}})).AsList(); + """; + } + + private string GetDriverNoTxBody(string sqlVar, string returnInterface, Query query) + { + var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); + var createSqlCommand = dbDriver.CreateSqlCommand(sqlVar); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + var initDataReader = CommonGen.InitDataReader(); + var awaitReaderRow = CommonGen.AwaitReaderRow(); + var dataclassInit = CommonGen.InstantiateDataclass(query.Columns.ToArray(), returnInterface); + var resultVar = Variable.Result.AsVarName(); + var readWhileExists = $$""" while ({{awaitReaderRow}}) { {{resultVar}}.Add({{dataclassInit}}); } """; - return $$""" + // TODO: add return null at end of code run so transaction code will not run? + return $$""" using ({{establishConnection}}) { - {{connectionOpen.AppendSemicolonUnlessEmpty()}}{{sqlTextTransform}} + {{connectionOpen.AppendSemicolonUnlessEmpty()}} using ({{createSqlCommand}}) { {{commandParameters}} @@ -77,6 +111,42 @@ string GetAsDriver() } } """; - } + } + + private string GetDriverWithTxBody(string sqlVar, string returnInterface, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var commandVar = Variable.Command.AsVarName(); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + var initDataReader = CommonGen.InitDataReader(); + var awaitReaderRow = CommonGen.AwaitReaderRow(); + var dataclassInit = CommonGen.InstantiateDataclass(query.Columns.ToArray(), returnInterface); + var resultVar = Variable.Result.AsVarName(); + var readWhileExists = $$""" + while ({{awaitReaderRow}}) + { + {{resultVar}}.Add({{dataclassInit}}); + } + """; + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var {{commandVar}} = this.{{transactionProperty}}.Connection.CreateCommand()) + { + {{commandVar}}.CommandText = {{sqlVar}}; + {{commandVar}}.Transaction = this.{{transactionProperty}}; + {{commandParameters}} + using ({{initDataReader}}) + { + var {{resultVar}} = new List<{{returnInterface}}>(); + {{readWhileExists}} + return {{resultVar}}; + } + } + """; } } \ No newline at end of file diff --git a/Drivers/Generators/OneDeclareGen.cs b/Drivers/Generators/OneDeclareGen.cs index d28a6a41..ab9f3190 100644 --- a/Drivers/Generators/OneDeclareGen.cs +++ b/Drivers/Generators/OneDeclareGen.cs @@ -24,55 +24,119 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte private string GetMethodBody(string queryTextConstant, string returnInterface, Query query) { - var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); var sqlTextTransform = CommonGen.GetSqlTransformations(query, queryTextConstant); - var connectionVar = Variable.Connection.AsVarName(); - var resultVar = Variable.Result.AsVarName(); var anyEmbeddedTableExists = query.Columns.Any(c => c.EmbedTable is not null); - return dbDriver.Options.UseDapper && !anyEmbeddedTableExists - ? GetAsDapper() - : GetAsDriver(); - - string GetAsDapper() - { - var dapperParamsSection = CommonGen.ConstructDapperParamsDict(query.Params); - var dapperArgs = dapperParamsSection != string.Empty ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; - var returnType = dbDriver.AddNullableSuffixIfNeeded(returnInterface, false); - - return $$""" - using ({{establishConnection}}) - {{{sqlTextTransform}}{{dapperParamsSection}} - var {{resultVar}} = await {{connectionVar}}.QueryFirstOrDefaultAsync<{{returnType}}>({{queryTextConstant}}{{dapperArgs}}); - return {{resultVar}}; + var useDapper = dbDriver.Options.UseDapper && !anyEmbeddedTableExists; + + var dapperParams = useDapper ? CommonGen.ConstructDapperParamsDict(query.Params) : string.Empty; + var sqlVar = sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant; + var transactionProperty = Variable.Transaction.AsPropertyName(); + + var noTxBody = useDapper ? GetDapperNoTxBody(sqlVar, returnInterface, query) : GetDriverNoTxBody(sqlVar, returnInterface, query); + var withTxBody = useDapper ? GetDapperWithTxBody(sqlVar, returnInterface, query) : GetDriverWithTxBody(sqlVar, returnInterface, query); + + return $$""" + {{sqlTextTransform}} + {{dapperParams}} + if (this.{{transactionProperty}} == null) + { + {{noTxBody}} + } + {{withTxBody}} + """; + } + + private string GetDapperNoTxBody(string sqlVar, string returnInterface, Query query) + { + var (establishConnection, _) = dbDriver.EstablishConnection(query); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + var returnType = dbDriver.AddNullableSuffixIfNeeded(returnInterface, false); + + return $$""" + using ({{establishConnection}}) + { + var {{Variable.Result.AsVarName()}} = await {{Variable.Connection.AsVarName()}}.QueryFirstOrDefaultAsync<{{returnType}}>({{sqlVar}}{{dapperArgs}}); + return {{Variable.Result.AsVarName()}}; + } + """; + } + + private string GetDapperWithTxBody(string sqlVar, string returnInterface, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var dapperArgs = query.Params.Any() ? $", {Variable.QueryParams.AsVarName()}" : string.Empty; + var returnType = dbDriver.AddNullableSuffixIfNeeded(returnInterface, false); + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.{{transactionProperty}}.Connection.QueryFirstOrDefaultAsync<{{returnType}}>( + {{sqlVar}}{{dapperArgs}}, + transaction: this.{{transactionProperty}}); + """; + } + + private string GetDriverNoTxBody(string sqlVar, string returnInterface, Query query) + { + var (establishConnection, connectionOpen) = dbDriver.EstablishConnection(query); + var createSqlCommand = dbDriver.CreateSqlCommand(sqlVar); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + var initDataReader = CommonGen.InitDataReader(); + var awaitReaderRow = CommonGen.AwaitReaderRow(); + var returnDataclass = CommonGen.InstantiateDataclass(query.Columns.ToArray(), returnInterface); + + return $$""" + using ({{establishConnection}}) + { + {{connectionOpen.AppendSemicolonUnlessEmpty()}} + using ({{createSqlCommand}}) + { + {{commandParameters}} + using ({{initDataReader}}) + { + if ({{awaitReaderRow}}) + { + return {{returnDataclass}}; + } + } + } + } + return null; + """; + } + + private string GetDriverWithTxBody(string sqlVar, string returnInterface, Query query) + { + var transactionProperty = Variable.Transaction.AsPropertyName(); + var commandVar = Variable.Command.AsVarName(); + var commandParameters = CommonGen.AddParametersToCommand(query.Params); + var initDataReader = CommonGen.InitDataReader(); + var awaitReaderRow = CommonGen.AwaitReaderRow(); + var returnDataclass = CommonGen.InstantiateDataclass(query.Columns.ToArray(), returnInterface); + + return $$""" + if (this.{{transactionProperty}}?.Connection == null || this.{{transactionProperty}}?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var {{commandVar}} = this.{{transactionProperty}}.Connection.CreateCommand()) + { + {{commandVar}}.CommandText = {{sqlVar}}; + {{commandVar}}.Transaction = this.{{transactionProperty}}; + {{commandParameters}} + using ({{initDataReader}}) + { + if ({{awaitReaderRow}}) + { + return {{returnDataclass}}; + } } - """; - } - - string GetAsDriver() - { - var createSqlCommand = dbDriver.CreateSqlCommand(sqlTextTransform != string.Empty ? Variable.TransformedSql.AsVarName() : queryTextConstant); - var commandParameters = CommonGen.AddParametersToCommand(query.Params); - var initDataReader = CommonGen.InitDataReader(); - var awaitReaderRow = CommonGen.AwaitReaderRow(); - var returnDataclass = CommonGen.InstantiateDataclass(query.Columns.ToArray(), returnInterface); - return $$""" - using ({{establishConnection}}) - { - {{connectionOpen.AppendSemicolonUnlessEmpty()}}{{sqlTextTransform}} - using ({{createSqlCommand}}) - { - {{commandParameters}} - using ({{initDataReader}}) - { - if ({{awaitReaderRow}}) - { - return {{returnDataclass}}; - } - } - } - } - return null; - """; - } + } + return null; + """; } } \ No newline at end of file diff --git a/Drivers/MySqlConnectorDriver.cs b/Drivers/MySqlConnectorDriver.cs index db741492..b649ca8f 100644 --- a/Drivers/MySqlConnectorDriver.cs +++ b/Drivers/MySqlConnectorDriver.cs @@ -95,6 +95,8 @@ public partial class MySqlConnectorDriver( }, ordinal => $"reader.GetDecimal({ordinal})") ]; + public override string TransactionClassName => "MySqlTransaction"; + public override UsingDirectiveSyntax[] GetUsingDirectivesForQueries() { return base.GetUsingDirectivesForQueries() diff --git a/Drivers/NpgsqlDriver.cs b/Drivers/NpgsqlDriver.cs index d0d68a25..f562c3df 100644 --- a/Drivers/NpgsqlDriver.cs +++ b/Drivers/NpgsqlDriver.cs @@ -153,6 +153,8 @@ public NpgsqlDriver( }, ordinal => $"reader.GetFieldValue({ordinal})") ]; + public override string TransactionClassName => "NpgsqlTransaction"; + public override UsingDirectiveSyntax[] GetUsingDirectivesForQueries() { return base.GetUsingDirectivesForQueries() @@ -198,6 +200,13 @@ public override string[] GetConstructorStatements() .ToArray(); } + public override string[] GetTransactionConstructorStatements() + { + return base.GetTransactionConstructorStatements() + .AppendIf("Utils.ConfigureSqlMapper();", Options.UseDapper) + .ToArray(); + } + public override MemberDeclarationSyntax[] GetMemberDeclarationsForUtils() { var memberDeclarations = base.GetMemberDeclarationsForUtils(); diff --git a/Drivers/SqliteDriver.cs b/Drivers/SqliteDriver.cs index dccfdf7e..ec37b043 100644 --- a/Drivers/SqliteDriver.cs +++ b/Drivers/SqliteDriver.cs @@ -39,6 +39,8 @@ public partial class SqliteDriver( }, ordinal => $"reader.GetDecimal({ordinal})"), ]; + public override string TransactionClassName => "SqliteTransaction"; + public override UsingDirectiveSyntax[] GetUsingDirectivesForQueries() { return base.GetUsingDirectivesForQueries() diff --git a/Drivers/Variable.cs b/Drivers/Variable.cs index 2d51d43e..1fbcc8ab 100644 --- a/Drivers/Variable.cs +++ b/Drivers/Variable.cs @@ -5,6 +5,7 @@ public enum Variable Options, Config, ConnectionString, + Transaction, Connection, Command, diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index c9396617..a9de91c1 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -1,10 +1,8 @@ -using MySqlConnector; using MySqlConnectorDapperExampleGen; using NUnit.Framework; using NUnit.Framework.Legacy; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -28,30 +26,6 @@ public async Task TestOne() Assert.That(SingularEquals(expected, actual)); } - [Test] - public async Task TestTransactionOne() - { - var connection = new MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); - await connection.OpenAsync(); - var transaction = connection.BeginTransaction(); - - var sqlQueryWithTx = new QuerySql(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); - Assert.That(actualNull == null, "there is author"); - await transaction.CommitAsync(); - - var expected = new QuerySql.GetAuthorRow - { - Id = 1111, - Name = "Bojack Horseman", - Bio = "Back in the 90s he was in a very famous TV show" - }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); - Assert.That(SingularEquals(expected, actual)); - } - private static bool SingularEquals(QuerySql.GetAuthorRow x, QuerySql.GetAuthorRow y) { return x.Id.Equals(y.Id) && x.Name.Equals(y.Name) && x.Bio.Equals(y.Bio); @@ -651,4 +625,4 @@ public async Task TestCopyFrom(int batchSize, MysqlTypesCEnum? cEnum) Assert.That(actual.CEnum, Is.EqualTo(expected.CEnum)); } } -} +} diff --git a/examples/MySqlConnectorDapperExample/QuerySql.cs b/examples/MySqlConnectorDapperExample/QuerySql.cs index 6c99b222..330f88af 100644 --- a/examples/MySqlConnectorDapperExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperExample/QuerySql.cs @@ -1,9 +1,9 @@ -// auto-generated by sqlc - do not edit -// ReSharper disable UseObjectOrCollectionInitializer -// ReSharper disable UseAwaitUsing -// ReSharper disable ConvertToUsingDeclaration -// ReSharper disable NotAccessedPositionalProperty.Global -// ReSharper disable UnusedAutoPropertyAccessor.Global +// auto-generated by sqlc - do not edit +// ReSharper disable UseObjectOrCollectionInitializer +// ReSharper disable UseAwaitUsing +// ReSharper disable ConvertToUsingDeclaration +// ReSharper disable NotAccessedPositionalProperty.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -19,23 +19,19 @@ namespace MySqlConnectorDapperExampleGen; public class QuerySql { - public QuerySql() - { - Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; - } - - public QuerySql(string connectionString) : this() + public QuerySql(string connectionString) { this.ConnectionString = connectionString; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - public QuerySql(MySqlTransaction transaction) : this() + public QuerySql(MySqlTransaction transaction) { - this.mySqlTransaction = transaction; + this.Transaction = transaction; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - private MySqlTransaction? mySqlTransaction { get; } - + private MySqlTransaction? Transaction { get; } private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1; SELECT LAST_INSERT_ID()"; @@ -53,7 +49,7 @@ public class GetAuthorArgs { var queryParams = new Dictionary(); queryParams.Add("name", args.Name); - if (this.mySqlTransaction == null) + if (this.Transaction == null) { using (var connection = new MySqlConnection(ConnectionString)) { @@ -62,15 +58,12 @@ public class GetAuthorArgs } } - if (this.mySqlTransaction?.Connection == null || this.mySqlTransaction?.Connection.State != System.Data.ConnectionState.Open) { - throw new InvalidOperationException("Transaction is provided, but its connection is null."); + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } - - return await mySqlTransaction.Connection.QueryFirstOrDefaultAsync( - GetAuthorSql, - queryParams, - transaction: this.mySqlTransaction); - + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams, transaction: this.Transaction); } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name; SELECT LAST_INSERT_ID()"; @@ -82,11 +75,21 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(ListAuthorsSql); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryAsync(ListAuthorsSql); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(ListAuthorsSql, transaction: this.Transaction)).AsList(); } private const string CreateAuthorSql = "INSERT INTO authors (id, name, bio) VALUES (@id, @name, @bio); SELECT LAST_INSERT_ID()"; @@ -102,23 +105,22 @@ public async Task CreateAuthor(CreateAuthorArgs args) queryParams.Add("id", args.Id); queryParams.Add("name", args.Name); queryParams.Add("bio", args.Bio); - if (this.mySqlTransaction == null) + if (this.Transaction == null) { using (var connection = new MySqlConnection(ConnectionString)) { await connection.ExecuteAsync(CreateAuthorSql, queryParams); } + + return; } - if (this.mySqlTransaction?.Connection == null || this.mySqlTransaction?.Connection.State != System.Data.ConnectionState.Open) + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - throw new InvalidOperationException("Transaction is provided, but its connection is null."); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } - - await mySqlTransaction.Connection.ExecuteAsync( - CreateAuthorSql, - queryParams, - transaction: this.mySqlTransaction); + + await this.Transaction.Connection.ExecuteAsync(CreateAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio); SELECT LAST_INSERT_ID()"; @@ -129,13 +131,23 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1; SELECT LAST_INSERT_ID()"; @@ -151,13 +163,23 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByNamePatternSql = "SELECT id, name, bio FROM authors WHERE name LIKE COALESCE(@name_pattern, '%'); SELECT LAST_INSERT_ID()"; @@ -173,13 +195,23 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name_pattern", args.NamePattern); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name_pattern", args.NamePattern); - var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorByNamePatternSql, queryParams, transaction: this.Transaction)).AsList(); } private const string DeleteAuthorSql = "DELETE FROM authors WHERE name = @name; SELECT LAST_INSERT_ID()"; @@ -189,21 +221,45 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAuthorSql, queryParams, transaction: this.Transaction); } private const string DeleteAllAuthorsSql = "DELETE FROM authors; SELECT LAST_INSERT_ID()"; public async Task DeleteAllAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAllAuthorsSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(DeleteAllAuthorsSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAllAuthorsSql, transaction: this.Transaction); } private const string UpdateAuthorsSql = "UPDATE authors SET bio = @bio WHERE bio IS NOT NULL ; SELECT LAST_INSERT_ID ( ) "; @@ -213,12 +269,22 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio", args.Bio); - return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.ExecuteAsync(UpdateAuthorsSql, queryParams, transaction: this.Transaction); } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids); SELECT LAST_INSERT_ID()"; @@ -234,16 +300,26 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + if (this.Transaction == null) { - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string GetAuthorsByIdsAndNamesSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids) AND name IN (/*SLICE:names*/@names); SELECT LAST_INSERT_ID()"; @@ -260,19 +336,29 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + queryParams.Add($"@namesArg{i}", args.Names[i]); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - queryParams.Add($"@namesArg{i}", args.Names[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string CreateBookSql = "INSERT INTO books (name, author_id) VALUES (@name, @author_id); SELECT LAST_INSERT_ID()"; @@ -283,13 +369,23 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("author_id", args.AuthorId); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("author_id", args.AuthorId); - return await connection.QuerySingleAsync(CreateBookSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateBookSql, queryParams); + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QuerySingleAsync(CreateBookSql, queryParams, transaction: this.Transaction); } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name ; SELECT LAST_INSERT_ID ( ) "; @@ -300,21 +396,45 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -327,21 +447,45 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -360,22 +504,47 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -421,46 +590,58 @@ public class InsertMysqlTypesArgs }; public async Task InsertMysqlTypes(InsertMysqlTypesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("c_bit", args.CBit); + queryParams.Add("c_bool", args.CBool); + queryParams.Add("c_boolean", args.CBoolean); + queryParams.Add("c_tinyint", args.CTinyint); + queryParams.Add("c_smallint", args.CSmallint); + queryParams.Add("c_mediumint", args.CMediumint); + queryParams.Add("c_int", args.CInt); + queryParams.Add("c_integer", args.CInteger); + queryParams.Add("c_bigint", args.CBigint); + queryParams.Add("c_decimal", args.CDecimal); + queryParams.Add("c_dec", args.CDec); + queryParams.Add("c_numeric", args.CNumeric); + queryParams.Add("c_fixed", args.CFixed); + queryParams.Add("c_float", args.CFloat); + queryParams.Add("c_double", args.CDouble); + queryParams.Add("c_double_precision", args.CDoublePrecision); + queryParams.Add("c_char", args.CChar); + queryParams.Add("c_nchar", args.CNchar); + queryParams.Add("c_national_char", args.CNationalChar); + queryParams.Add("c_varchar", args.CVarchar); + queryParams.Add("c_tinytext", args.CTinytext); + queryParams.Add("c_mediumtext", args.CMediumtext); + queryParams.Add("c_text", args.CText); + queryParams.Add("c_longtext", args.CLongtext); + queryParams.Add("c_enum", args.CEnum); + queryParams.Add("c_year", args.CYear); + queryParams.Add("c_date", args.CDate); + queryParams.Add("c_datetime", args.CDatetime); + queryParams.Add("c_timestamp", args.CTimestamp); + queryParams.Add("c_binary", args.CBinary); + queryParams.Add("c_varbinary", args.CVarbinary); + queryParams.Add("c_tinyblob", args.CTinyblob); + queryParams.Add("c_blob", args.CBlob); + queryParams.Add("c_mediumblob", args.CMediumblob); + queryParams.Add("c_longblob", args.CLongblob); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("c_bit", args.CBit); - queryParams.Add("c_bool", args.CBool); - queryParams.Add("c_boolean", args.CBoolean); - queryParams.Add("c_tinyint", args.CTinyint); - queryParams.Add("c_smallint", args.CSmallint); - queryParams.Add("c_mediumint", args.CMediumint); - queryParams.Add("c_int", args.CInt); - queryParams.Add("c_integer", args.CInteger); - queryParams.Add("c_bigint", args.CBigint); - queryParams.Add("c_decimal", args.CDecimal); - queryParams.Add("c_dec", args.CDec); - queryParams.Add("c_numeric", args.CNumeric); - queryParams.Add("c_fixed", args.CFixed); - queryParams.Add("c_float", args.CFloat); - queryParams.Add("c_double", args.CDouble); - queryParams.Add("c_double_precision", args.CDoublePrecision); - queryParams.Add("c_char", args.CChar); - queryParams.Add("c_nchar", args.CNchar); - queryParams.Add("c_national_char", args.CNationalChar); - queryParams.Add("c_varchar", args.CVarchar); - queryParams.Add("c_tinytext", args.CTinytext); - queryParams.Add("c_mediumtext", args.CMediumtext); - queryParams.Add("c_text", args.CText); - queryParams.Add("c_longtext", args.CLongtext); - queryParams.Add("c_enum", args.CEnum); - queryParams.Add("c_year", args.CYear); - queryParams.Add("c_date", args.CDate); - queryParams.Add("c_datetime", args.CDatetime); - queryParams.Add("c_timestamp", args.CTimestamp); - queryParams.Add("c_binary", args.CBinary); - queryParams.Add("c_varbinary", args.CVarbinary); - queryParams.Add("c_tinyblob", args.CTinyblob); - queryParams.Add("c_blob", args.CBlob); - queryParams.Add("c_mediumblob", args.CMediumblob); - queryParams.Add("c_longblob", args.CLongblob); - await connection.ExecuteAsync(InsertMysqlTypesSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertMysqlTypesSql, queryParams); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(InsertMysqlTypesSql, queryParams, transaction: this.Transaction); } public class InsertMysqlTypesBatchArgs @@ -604,11 +785,21 @@ public class GetMysqlTypesRow }; public async Task GetMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetMysqlTypesSql, transaction: this.Transaction); } private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float , c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_enum, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob FROM mysql_types GROUP BY c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_enum, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob LIMIT 1 ; SELECT LAST_INSERT_ID ( ) "; @@ -653,20 +844,42 @@ public class GetMysqlTypesAggRow }; public async Task GetMysqlTypesAgg() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesAggSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesAggSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetMysqlTypesAggSql, transaction: this.Transaction); } private const string TruncateMysqlTypesSql = "TRUNCATE TABLE mysql_types; SELECT LAST_INSERT_ID()"; public async Task TruncateMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncateMysqlTypesSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(TruncateMysqlTypesSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(TruncateMysqlTypesSql, transaction: this.Transaction); } private const string CreateExtendedBioSql = "INSERT INTO extended.bios (author_name, name, bio_type) VALUES (@author_name, @name, @bio_type); SELECT LAST_INSERT_ID()"; @@ -678,14 +891,26 @@ public class CreateExtendedBioArgs }; public async Task CreateExtendedBio(CreateExtendedBioArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("author_name", args.AuthorName); + queryParams.Add("name", args.Name); + queryParams.Add("bio_type", args.BioType); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("author_name", args.AuthorName); - queryParams.Add("name", args.Name); - queryParams.Add("bio_type", args.BioType); - await connection.ExecuteAsync(CreateExtendedBioSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(CreateExtendedBioSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(CreateExtendedBioSql, queryParams, transaction: this.Transaction); } private const string GetFirstExtendedBioByTypeSql = "SELECT author_name, name, bio_type FROM extended.bios WHERE bio_type = @bio_type LIMIT 1; SELECT LAST_INSERT_ID()"; @@ -701,21 +926,43 @@ public class GetFirstExtendedBioByTypeArgs }; public async Task GetFirstExtendedBioByType(GetFirstExtendedBioByTypeArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio_type", args.BioType); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("bio_type", args.BioType); - var result = await connection.QueryFirstOrDefaultAsync(GetFirstExtendedBioByTypeSql, queryParams); - return result; + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetFirstExtendedBioByTypeSql, queryParams); + return result; + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetFirstExtendedBioByTypeSql, queryParams, transaction: this.Transaction); } private const string TruncateExtendedBiosSql = "TRUNCATE TABLE extended.bios; SELECT LAST_INSERT_ID()"; public async Task TruncateExtendedBios() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncateExtendedBiosSql); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncateExtendedBiosSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(TruncateExtendedBiosSql, transaction: this.Transaction); } } \ No newline at end of file diff --git a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs index 41d699ac..51ad4714 100644 --- a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs @@ -26,6 +26,13 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } + public QuerySql(MySqlTransaction transaction) + { + this.Transaction = transaction; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; + } + + private MySqlTransaction Transaction { get; } private string ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1; SELECT LAST_INSERT_ID()"; @@ -41,13 +48,23 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams, transaction: this.Transaction); } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name; SELECT LAST_INSERT_ID()"; @@ -59,11 +76,21 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - var result = await connection.QueryAsync(ListAuthorsSql); - return result.AsList(); + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(ListAuthorsSql); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(ListAuthorsSql, transaction: this.Transaction)).AsList(); } private const string CreateAuthorSql = "INSERT INTO authors (id, name, bio) VALUES (@id, @name, @bio); SELECT LAST_INSERT_ID()"; @@ -75,14 +102,26 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(CreateAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - await connection.ExecuteAsync(CreateAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(CreateAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio); SELECT LAST_INSERT_ID()"; @@ -93,13 +132,23 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1; SELECT LAST_INSERT_ID()"; @@ -115,13 +164,23 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); - return result; + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByNamePatternSql = "SELECT id, name, bio FROM authors WHERE name LIKE COALESCE(@name_pattern, '%'); SELECT LAST_INSERT_ID()"; @@ -137,13 +196,23 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name_pattern", args.NamePattern); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name_pattern", args.NamePattern); - var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorByNamePatternSql, queryParams, transaction: this.Transaction)).AsList(); } private const string DeleteAuthorSql = "DELETE FROM authors WHERE name = @name; SELECT LAST_INSERT_ID()"; @@ -153,21 +222,45 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAuthorSql, queryParams, transaction: this.Transaction); } private const string DeleteAllAuthorsSql = "DELETE FROM authors; SELECT LAST_INSERT_ID()"; public async Task DeleteAllAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(DeleteAllAuthorsSql); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAllAuthorsSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAllAuthorsSql, transaction: this.Transaction); } private const string UpdateAuthorsSql = "UPDATE authors SET bio = @bio WHERE bio IS NOT NULL ; SELECT LAST_INSERT_ID ( ) "; @@ -177,12 +270,22 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio", args.Bio); - return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.ExecuteAsync(UpdateAuthorsSql, queryParams, transaction: this.Transaction); } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids); SELECT LAST_INSERT_ID()"; @@ -198,16 +301,26 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string GetAuthorsByIdsAndNamesSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids) AND name IN (/*SLICE:names*/@names); SELECT LAST_INSERT_ID()"; @@ -224,19 +337,29 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + queryParams.Add($"@namesArg{i}", args.Names[i]); + if (this.Transaction == null) { - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - queryParams.Add($"@namesArg{i}", args.Names[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string CreateBookSql = "INSERT INTO books (name, author_id) VALUES (@name, @author_id); SELECT LAST_INSERT_ID()"; @@ -247,13 +370,23 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("author_id", args.AuthorId); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("author_id", args.AuthorId); - return await connection.QuerySingleAsync(CreateBookSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateBookSql, queryParams); + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QuerySingleAsync(CreateBookSql, queryParams, transaction: this.Transaction); } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name ; SELECT LAST_INSERT_ID ( ) "; @@ -264,21 +397,45 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -291,21 +448,45 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -324,22 +505,47 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -385,46 +591,58 @@ public class InsertMysqlTypesArgs }; public async Task InsertMysqlTypes(InsertMysqlTypesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("c_bit", args.CBit); + queryParams.Add("c_bool", args.CBool); + queryParams.Add("c_boolean", args.CBoolean); + queryParams.Add("c_tinyint", args.CTinyint); + queryParams.Add("c_smallint", args.CSmallint); + queryParams.Add("c_mediumint", args.CMediumint); + queryParams.Add("c_int", args.CInt); + queryParams.Add("c_integer", args.CInteger); + queryParams.Add("c_bigint", args.CBigint); + queryParams.Add("c_decimal", args.CDecimal); + queryParams.Add("c_dec", args.CDec); + queryParams.Add("c_numeric", args.CNumeric); + queryParams.Add("c_fixed", args.CFixed); + queryParams.Add("c_float", args.CFloat); + queryParams.Add("c_double", args.CDouble); + queryParams.Add("c_double_precision", args.CDoublePrecision); + queryParams.Add("c_char", args.CChar); + queryParams.Add("c_nchar", args.CNchar); + queryParams.Add("c_national_char", args.CNationalChar); + queryParams.Add("c_varchar", args.CVarchar); + queryParams.Add("c_tinytext", args.CTinytext); + queryParams.Add("c_mediumtext", args.CMediumtext); + queryParams.Add("c_text", args.CText); + queryParams.Add("c_longtext", args.CLongtext); + queryParams.Add("c_enum", args.CEnum); + queryParams.Add("c_year", args.CYear); + queryParams.Add("c_date", args.CDate); + queryParams.Add("c_datetime", args.CDatetime); + queryParams.Add("c_timestamp", args.CTimestamp); + queryParams.Add("c_binary", args.CBinary); + queryParams.Add("c_varbinary", args.CVarbinary); + queryParams.Add("c_tinyblob", args.CTinyblob); + queryParams.Add("c_blob", args.CBlob); + queryParams.Add("c_mediumblob", args.CMediumblob); + queryParams.Add("c_longblob", args.CLongblob); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("c_bit", args.CBit); - queryParams.Add("c_bool", args.CBool); - queryParams.Add("c_boolean", args.CBoolean); - queryParams.Add("c_tinyint", args.CTinyint); - queryParams.Add("c_smallint", args.CSmallint); - queryParams.Add("c_mediumint", args.CMediumint); - queryParams.Add("c_int", args.CInt); - queryParams.Add("c_integer", args.CInteger); - queryParams.Add("c_bigint", args.CBigint); - queryParams.Add("c_decimal", args.CDecimal); - queryParams.Add("c_dec", args.CDec); - queryParams.Add("c_numeric", args.CNumeric); - queryParams.Add("c_fixed", args.CFixed); - queryParams.Add("c_float", args.CFloat); - queryParams.Add("c_double", args.CDouble); - queryParams.Add("c_double_precision", args.CDoublePrecision); - queryParams.Add("c_char", args.CChar); - queryParams.Add("c_nchar", args.CNchar); - queryParams.Add("c_national_char", args.CNationalChar); - queryParams.Add("c_varchar", args.CVarchar); - queryParams.Add("c_tinytext", args.CTinytext); - queryParams.Add("c_mediumtext", args.CMediumtext); - queryParams.Add("c_text", args.CText); - queryParams.Add("c_longtext", args.CLongtext); - queryParams.Add("c_enum", args.CEnum); - queryParams.Add("c_year", args.CYear); - queryParams.Add("c_date", args.CDate); - queryParams.Add("c_datetime", args.CDatetime); - queryParams.Add("c_timestamp", args.CTimestamp); - queryParams.Add("c_binary", args.CBinary); - queryParams.Add("c_varbinary", args.CVarbinary); - queryParams.Add("c_tinyblob", args.CTinyblob); - queryParams.Add("c_blob", args.CBlob); - queryParams.Add("c_mediumblob", args.CMediumblob); - queryParams.Add("c_longblob", args.CLongblob); - await connection.ExecuteAsync(InsertMysqlTypesSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertMysqlTypesSql, queryParams); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(InsertMysqlTypesSql, queryParams, transaction: this.Transaction); } public class InsertMysqlTypesBatchArgs @@ -567,11 +785,21 @@ public class GetMysqlTypesRow }; public async Task GetMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetMysqlTypesSql, transaction: this.Transaction); } private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float , c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_enum, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob FROM mysql_types GROUP BY c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_enum, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob LIMIT 1 ; SELECT LAST_INSERT_ID ( ) "; @@ -616,20 +844,42 @@ public class GetMysqlTypesAggRow }; public async Task GetMysqlTypesAgg() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesAggSql); - return result; + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetMysqlTypesAggSql); + return result; + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetMysqlTypesAggSql, transaction: this.Transaction); } private const string TruncateMysqlTypesSql = "TRUNCATE TABLE mysql_types; SELECT LAST_INSERT_ID()"; public async Task TruncateMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncateMysqlTypesSql); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncateMysqlTypesSql); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(TruncateMysqlTypesSql, transaction: this.Transaction); } private const string CreateExtendedBioSql = "INSERT INTO extended.bios (author_name, name, bio_type) VALUES (@author_name, @name, @bio_type); SELECT LAST_INSERT_ID()"; @@ -641,14 +891,26 @@ public class CreateExtendedBioArgs }; public async Task CreateExtendedBio(CreateExtendedBioArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("author_name", args.AuthorName); + queryParams.Add("name", args.Name); + queryParams.Add("bio_type", args.BioType); + if (this.Transaction == null) { - var queryParams = new Dictionary(); - queryParams.Add("author_name", args.AuthorName); - queryParams.Add("name", args.Name); - queryParams.Add("bio_type", args.BioType); - await connection.ExecuteAsync(CreateExtendedBioSql, queryParams); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(CreateExtendedBioSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(CreateExtendedBioSql, queryParams, transaction: this.Transaction); } private const string GetFirstExtendedBioByTypeSql = "SELECT author_name, name, bio_type FROM extended.bios WHERE bio_type = @bio_type LIMIT 1; SELECT LAST_INSERT_ID()"; @@ -664,22 +926,44 @@ public class GetFirstExtendedBioByTypeArgs }; public async Task GetFirstExtendedBioByType(GetFirstExtendedBioByTypeArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio_type", args.BioType); + if (this.Transaction == null) + { + using (var connection = new MySqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetFirstExtendedBioByTypeSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio_type", args.BioType); - var result = await connection.QueryFirstOrDefaultAsync(GetFirstExtendedBioByTypeSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetFirstExtendedBioByTypeSql, queryParams, transaction: this.Transaction); } private const string TruncateExtendedBiosSql = "TRUNCATE TABLE extended.bios; SELECT LAST_INSERT_ID()"; public async Task TruncateExtendedBios() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncateExtendedBiosSql); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncateExtendedBiosSql); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(TruncateExtendedBiosSql, transaction: this.Transaction); } } } \ No newline at end of file diff --git a/examples/MySqlConnectorExample/QuerySql.cs b/examples/MySqlConnectorExample/QuerySql.cs index a30e423e..512c991f 100644 --- a/examples/MySqlConnectorExample/QuerySql.cs +++ b/examples/MySqlConnectorExample/QuerySql.cs @@ -23,32 +23,67 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - private string ConnectionString { get; } + public QuerySql(MySqlTransaction transaction) + { + this.Transaction = transaction; + } + + private MySqlTransaction? Transaction { get; } + private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; public readonly record struct GetAuthorRow(long Id, string Name, string? Bio); public readonly record struct GetAuthorArgs(string Name); public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -58,21 +93,45 @@ public QuerySql(string connectionString) public readonly record struct ListAuthorsRow(long Id, string Name, string? Bio); public async Task> ListAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(ListAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(ListAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -81,16 +140,36 @@ public async Task> ListAuthors() public readonly record struct CreateAuthorArgs(long Id, string Name, string? Bio); public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateAuthorSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateAuthorSql, connection)) + { + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -98,17 +177,35 @@ public async Task CreateAuthor(CreateAuthorArgs args) public readonly record struct CreateAuthorReturnIdArgs(string Name, string? Bio); public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateAuthorReturnIdSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - await command.ExecuteNonQueryAsync(); - return command.LastInsertedId; + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateAuthorReturnIdSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorReturnIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -116,25 +213,54 @@ public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) public readonly record struct GetAuthorByIdArgs(long Id); public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorByIdSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorByIdSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorByIdRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -145,22 +271,47 @@ public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) public readonly record struct GetAuthorByNamePatternArgs(string? NamePattern); public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorByNamePatternSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorByNamePatternSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByNamePatternSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -169,27 +320,62 @@ public async Task> GetAuthorByNamePattern(GetAut public readonly record struct DeleteAuthorArgs(string Name); public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(DeleteAuthorSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(DeleteAuthorSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); } } private const string DeleteAllAuthorsSql = "DELETE FROM authors"; public async Task DeleteAllAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(DeleteAllAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(DeleteAllAuthorsSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAllAuthorsSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -197,15 +383,31 @@ public async Task DeleteAllAuthors() public readonly record struct UpdateAuthorsArgs(string? Bio); public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(UpdateAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - return await command.ExecuteNonQueryAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(UpdateAuthorsSql, connection)) + { + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = UpdateAuthorsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids)"; @@ -213,25 +415,51 @@ public async Task UpdateAuthors(UpdateAuthorsArgs args) public readonly record struct GetAuthorsByIdsArgs(long[] Ids); public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - using (var command = new MySqlCommand(transformedSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(transformedSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -241,28 +469,56 @@ public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs public readonly record struct GetAuthorsByIdsAndNamesArgs(long[] Ids, string[] Names); public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - using (var command = new MySqlCommand(transformedSql, connection)) - { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); - using (var reader = await command.ExecuteReaderAsync()) - { - var result = new List(); - while (await reader.ReadAsync()) + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.OpenAsync(); + using (var command = new MySqlCommand(transformedSql, connection)) + { + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -271,38 +527,80 @@ public async Task> GetAuthorsByIdsAndNames(GetA public readonly record struct CreateBookArgs(string Name, long AuthorId); public async Task CreateBook(CreateBookArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateBookSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@author_id", args.AuthorId); - await command.ExecuteNonQueryAsync(); - return command.LastInsertedId; + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateBookSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateBookSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name "; public readonly record struct ListAllAuthorsBooksRow(Author? Author, Book? Book); public async Task> ListAllAuthorsBooks() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -311,21 +609,45 @@ public async Task> ListAllAuthorsBooks() public readonly record struct GetDuplicateAuthorsRow(Author? Author, Author? Author2); public async Task> GetDuplicateAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -335,22 +657,47 @@ public async Task> GetDuplicateAuthors() public readonly record struct GetAuthorsByBookNameArgs(string Name); public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -359,48 +706,100 @@ public async Task> GetAuthorsByBookName(GetAuthors public readonly record struct InsertMysqlTypesArgs(byte? CBit, bool? CBool, bool? CBoolean, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, decimal? CDecimal, decimal? CDec, decimal? CNumeric, decimal? CFixed, double? CFloat, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, MysqlTypesCEnum? CEnum, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob); public async Task InsertMysqlTypes(InsertMysqlTypesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(InsertMysqlTypesSql, connection)) - { - command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_dec", args.CDec ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_fixed", args.CFixed ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_float", args.CFloat ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_double", args.CDouble ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_nchar", args.CNchar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_national_char", args.CNationalChar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_tinytext", args.CTinytext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_enum", args.CEnum ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_tinyblob", args.CTinyblob ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_mediumblob", args.CMediumblob ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_longblob", args.CLongblob ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.OpenAsync(); + using (var command = new MySqlCommand(InsertMysqlTypesSql, connection)) + { + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_dec", args.CDec ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_fixed", args.CFixed ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_float", args.CFloat ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double", args.CDouble ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_nchar", args.CNchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_national_char", args.CNationalChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinytext", args.CTinytext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_enum", args.CEnum ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyblob", args.CTinyblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumblob", args.CMediumblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longblob", args.CLongblob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertMysqlTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_dec", args.CDec ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_fixed", args.CFixed ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_float", args.CFloat ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double", args.CDouble ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_nchar", args.CNchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_national_char", args.CNationalChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinytext", args.CTinytext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_enum", args.CEnum ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyblob", args.CTinyblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumblob", args.CMediumblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longblob", args.CLongblob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -470,57 +869,118 @@ public async Task InsertMysqlTypesBatch(List args) public readonly record struct GetMysqlTypesRow(bool? CBool, bool? CBoolean, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, double? CFloat, decimal? CDecimal, decimal? CDec, decimal? CNumeric, decimal? CFixed, double? CDouble, double? CDoublePrecision, short? CYear, DateTime? CDate, string? CTime, DateTime? CDatetime, DateTime? CTimestamp, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, MysqlTypesCEnum? CEnum, byte? CBit, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob); public async Task GetMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetMysqlTypesSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetMysqlTypesSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetMysqlTypesRow + if (await reader.ReadAsync()) { - CBool = reader.IsDBNull(0) ? null : reader.GetBoolean(0), - CBoolean = reader.IsDBNull(1) ? null : reader.GetBoolean(1), - CTinyint = reader.IsDBNull(2) ? null : reader.GetInt16(2), - CSmallint = reader.IsDBNull(3) ? null : reader.GetInt16(3), - CMediumint = reader.IsDBNull(4) ? null : reader.GetInt32(4), - CInt = reader.IsDBNull(5) ? null : reader.GetInt32(5), - CInteger = reader.IsDBNull(6) ? null : reader.GetInt32(6), - CBigint = reader.IsDBNull(7) ? null : reader.GetInt64(7), - CFloat = reader.IsDBNull(8) ? null : reader.GetDouble(8), - CDecimal = reader.IsDBNull(9) ? null : reader.GetDecimal(9), - CDec = reader.IsDBNull(10) ? null : reader.GetDecimal(10), - CNumeric = reader.IsDBNull(11) ? null : reader.GetDecimal(11), - CFixed = reader.IsDBNull(12) ? null : reader.GetDecimal(12), - CDouble = reader.IsDBNull(13) ? null : reader.GetDouble(13), - CDoublePrecision = reader.IsDBNull(14) ? null : reader.GetDouble(14), - CYear = reader.IsDBNull(15) ? null : reader.GetInt16(15), - CDate = reader.IsDBNull(16) ? null : reader.GetDateTime(16), - CTime = reader.IsDBNull(17) ? null : reader.GetString(17), - CDatetime = reader.IsDBNull(18) ? null : reader.GetDateTime(18), - CTimestamp = reader.IsDBNull(19) ? null : reader.GetDateTime(19), - CChar = reader.IsDBNull(20) ? null : reader.GetString(20), - CNchar = reader.IsDBNull(21) ? null : reader.GetString(21), - CNationalChar = reader.IsDBNull(22) ? null : reader.GetString(22), - CVarchar = reader.IsDBNull(23) ? null : reader.GetString(23), - CTinytext = reader.IsDBNull(24) ? null : reader.GetString(24), - CMediumtext = reader.IsDBNull(25) ? null : reader.GetString(25), - CText = reader.IsDBNull(26) ? null : reader.GetString(26), - CLongtext = reader.IsDBNull(27) ? null : reader.GetString(27), - CEnum = reader.IsDBNull(28) ? null : reader.GetString(28).ToMysqlTypesCEnum(), - CBit = reader.IsDBNull(29) ? null : reader.GetFieldValue(29), - CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), - CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), - CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), - CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), - CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), - CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) - }; + return new GetMysqlTypesRow + { + CBool = reader.IsDBNull(0) ? null : reader.GetBoolean(0), + CBoolean = reader.IsDBNull(1) ? null : reader.GetBoolean(1), + CTinyint = reader.IsDBNull(2) ? null : reader.GetInt16(2), + CSmallint = reader.IsDBNull(3) ? null : reader.GetInt16(3), + CMediumint = reader.IsDBNull(4) ? null : reader.GetInt32(4), + CInt = reader.IsDBNull(5) ? null : reader.GetInt32(5), + CInteger = reader.IsDBNull(6) ? null : reader.GetInt32(6), + CBigint = reader.IsDBNull(7) ? null : reader.GetInt64(7), + CFloat = reader.IsDBNull(8) ? null : reader.GetDouble(8), + CDecimal = reader.IsDBNull(9) ? null : reader.GetDecimal(9), + CDec = reader.IsDBNull(10) ? null : reader.GetDecimal(10), + CNumeric = reader.IsDBNull(11) ? null : reader.GetDecimal(11), + CFixed = reader.IsDBNull(12) ? null : reader.GetDecimal(12), + CDouble = reader.IsDBNull(13) ? null : reader.GetDouble(13), + CDoublePrecision = reader.IsDBNull(14) ? null : reader.GetDouble(14), + CYear = reader.IsDBNull(15) ? null : reader.GetInt16(15), + CDate = reader.IsDBNull(16) ? null : reader.GetDateTime(16), + CTime = reader.IsDBNull(17) ? null : reader.GetString(17), + CDatetime = reader.IsDBNull(18) ? null : reader.GetDateTime(18), + CTimestamp = reader.IsDBNull(19) ? null : reader.GetDateTime(19), + CChar = reader.IsDBNull(20) ? null : reader.GetString(20), + CNchar = reader.IsDBNull(21) ? null : reader.GetString(21), + CNationalChar = reader.IsDBNull(22) ? null : reader.GetString(22), + CVarchar = reader.IsDBNull(23) ? null : reader.GetString(23), + CTinytext = reader.IsDBNull(24) ? null : reader.GetString(24), + CMediumtext = reader.IsDBNull(25) ? null : reader.GetString(25), + CText = reader.IsDBNull(26) ? null : reader.GetString(26), + CLongtext = reader.IsDBNull(27) ? null : reader.GetString(27), + CEnum = reader.IsDBNull(28) ? null : reader.GetString(28).ToMysqlTypesCEnum(), + CBit = reader.IsDBNull(29) ? null : reader.GetFieldValue(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetMysqlTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetMysqlTypesRow + { + CBool = reader.IsDBNull(0) ? null : reader.GetBoolean(0), + CBoolean = reader.IsDBNull(1) ? null : reader.GetBoolean(1), + CTinyint = reader.IsDBNull(2) ? null : reader.GetInt16(2), + CSmallint = reader.IsDBNull(3) ? null : reader.GetInt16(3), + CMediumint = reader.IsDBNull(4) ? null : reader.GetInt32(4), + CInt = reader.IsDBNull(5) ? null : reader.GetInt32(5), + CInteger = reader.IsDBNull(6) ? null : reader.GetInt32(6), + CBigint = reader.IsDBNull(7) ? null : reader.GetInt64(7), + CFloat = reader.IsDBNull(8) ? null : reader.GetDouble(8), + CDecimal = reader.IsDBNull(9) ? null : reader.GetDecimal(9), + CDec = reader.IsDBNull(10) ? null : reader.GetDecimal(10), + CNumeric = reader.IsDBNull(11) ? null : reader.GetDecimal(11), + CFixed = reader.IsDBNull(12) ? null : reader.GetDecimal(12), + CDouble = reader.IsDBNull(13) ? null : reader.GetDouble(13), + CDoublePrecision = reader.IsDBNull(14) ? null : reader.GetDouble(14), + CYear = reader.IsDBNull(15) ? null : reader.GetInt16(15), + CDate = reader.IsDBNull(16) ? null : reader.GetDateTime(16), + CTime = reader.IsDBNull(17) ? null : reader.GetString(17), + CDatetime = reader.IsDBNull(18) ? null : reader.GetDateTime(18), + CTimestamp = reader.IsDBNull(19) ? null : reader.GetDateTime(19), + CChar = reader.IsDBNull(20) ? null : reader.GetString(20), + CNchar = reader.IsDBNull(21) ? null : reader.GetString(21), + CNationalChar = reader.IsDBNull(22) ? null : reader.GetString(22), + CVarchar = reader.IsDBNull(23) ? null : reader.GetString(23), + CTinytext = reader.IsDBNull(24) ? null : reader.GetString(24), + CMediumtext = reader.IsDBNull(25) ? null : reader.GetString(25), + CText = reader.IsDBNull(26) ? null : reader.GetString(26), + CLongtext = reader.IsDBNull(27) ? null : reader.GetString(27), + CEnum = reader.IsDBNull(28) ? null : reader.GetString(28).ToMysqlTypesCEnum(), + CBit = reader.IsDBNull(29) ? null : reader.GetFieldValue(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } + } } return null; @@ -530,57 +990,118 @@ public async Task InsertMysqlTypesBatch(List args) public readonly record struct GetMysqlTypesAggRow(long Cnt, bool? CBool, bool? CBoolean, byte? CBit, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, double? CFloat, decimal? CNumeric, decimal? CDecimal, decimal? CDec, decimal? CFixed, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, MysqlTypesCEnum? CEnum, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob); public async Task GetMysqlTypesAgg() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetMysqlTypesAggSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetMysqlTypesAggSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetMysqlTypesAggRow + if (await reader.ReadAsync()) { - Cnt = reader.GetInt64(0), - CBool = reader.IsDBNull(1) ? null : reader.GetBoolean(1), - CBoolean = reader.IsDBNull(2) ? null : reader.GetBoolean(2), - CBit = reader.IsDBNull(3) ? null : reader.GetFieldValue(3), - CTinyint = reader.IsDBNull(4) ? null : reader.GetInt16(4), - CSmallint = reader.IsDBNull(5) ? null : reader.GetInt16(5), - CMediumint = reader.IsDBNull(6) ? null : reader.GetInt32(6), - CInt = reader.IsDBNull(7) ? null : reader.GetInt32(7), - CInteger = reader.IsDBNull(8) ? null : reader.GetInt32(8), - CBigint = reader.IsDBNull(9) ? null : reader.GetInt64(9), - CFloat = reader.IsDBNull(10) ? null : reader.GetDouble(10), - CNumeric = reader.IsDBNull(11) ? null : reader.GetDecimal(11), - CDecimal = reader.IsDBNull(12) ? null : reader.GetDecimal(12), - CDec = reader.IsDBNull(13) ? null : reader.GetDecimal(13), - CFixed = reader.IsDBNull(14) ? null : reader.GetDecimal(14), - CDouble = reader.IsDBNull(15) ? null : reader.GetDouble(15), - CDoublePrecision = reader.IsDBNull(16) ? null : reader.GetDouble(16), - CChar = reader.IsDBNull(17) ? null : reader.GetString(17), - CNchar = reader.IsDBNull(18) ? null : reader.GetString(18), - CNationalChar = reader.IsDBNull(19) ? null : reader.GetString(19), - CVarchar = reader.IsDBNull(20) ? null : reader.GetString(20), - CTinytext = reader.IsDBNull(21) ? null : reader.GetString(21), - CMediumtext = reader.IsDBNull(22) ? null : reader.GetString(22), - CText = reader.IsDBNull(23) ? null : reader.GetString(23), - CLongtext = reader.IsDBNull(24) ? null : reader.GetString(24), - CEnum = reader.IsDBNull(25) ? null : reader.GetString(25).ToMysqlTypesCEnum(), - CYear = reader.IsDBNull(26) ? null : reader.GetInt16(26), - CDate = reader.IsDBNull(27) ? null : reader.GetDateTime(27), - CDatetime = reader.IsDBNull(28) ? null : reader.GetDateTime(28), - CTimestamp = reader.IsDBNull(29) ? null : reader.GetDateTime(29), - CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), - CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), - CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), - CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), - CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), - CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) - }; + return new GetMysqlTypesAggRow + { + Cnt = reader.GetInt64(0), + CBool = reader.IsDBNull(1) ? null : reader.GetBoolean(1), + CBoolean = reader.IsDBNull(2) ? null : reader.GetBoolean(2), + CBit = reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + CTinyint = reader.IsDBNull(4) ? null : reader.GetInt16(4), + CSmallint = reader.IsDBNull(5) ? null : reader.GetInt16(5), + CMediumint = reader.IsDBNull(6) ? null : reader.GetInt32(6), + CInt = reader.IsDBNull(7) ? null : reader.GetInt32(7), + CInteger = reader.IsDBNull(8) ? null : reader.GetInt32(8), + CBigint = reader.IsDBNull(9) ? null : reader.GetInt64(9), + CFloat = reader.IsDBNull(10) ? null : reader.GetDouble(10), + CNumeric = reader.IsDBNull(11) ? null : reader.GetDecimal(11), + CDecimal = reader.IsDBNull(12) ? null : reader.GetDecimal(12), + CDec = reader.IsDBNull(13) ? null : reader.GetDecimal(13), + CFixed = reader.IsDBNull(14) ? null : reader.GetDecimal(14), + CDouble = reader.IsDBNull(15) ? null : reader.GetDouble(15), + CDoublePrecision = reader.IsDBNull(16) ? null : reader.GetDouble(16), + CChar = reader.IsDBNull(17) ? null : reader.GetString(17), + CNchar = reader.IsDBNull(18) ? null : reader.GetString(18), + CNationalChar = reader.IsDBNull(19) ? null : reader.GetString(19), + CVarchar = reader.IsDBNull(20) ? null : reader.GetString(20), + CTinytext = reader.IsDBNull(21) ? null : reader.GetString(21), + CMediumtext = reader.IsDBNull(22) ? null : reader.GetString(22), + CText = reader.IsDBNull(23) ? null : reader.GetString(23), + CLongtext = reader.IsDBNull(24) ? null : reader.GetString(24), + CEnum = reader.IsDBNull(25) ? null : reader.GetString(25).ToMysqlTypesCEnum(), + CYear = reader.IsDBNull(26) ? null : reader.GetInt16(26), + CDate = reader.IsDBNull(27) ? null : reader.GetDateTime(27), + CDatetime = reader.IsDBNull(28) ? null : reader.GetDateTime(28), + CTimestamp = reader.IsDBNull(29) ? null : reader.GetDateTime(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetMysqlTypesAggSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetMysqlTypesAggRow + { + Cnt = reader.GetInt64(0), + CBool = reader.IsDBNull(1) ? null : reader.GetBoolean(1), + CBoolean = reader.IsDBNull(2) ? null : reader.GetBoolean(2), + CBit = reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + CTinyint = reader.IsDBNull(4) ? null : reader.GetInt16(4), + CSmallint = reader.IsDBNull(5) ? null : reader.GetInt16(5), + CMediumint = reader.IsDBNull(6) ? null : reader.GetInt32(6), + CInt = reader.IsDBNull(7) ? null : reader.GetInt32(7), + CInteger = reader.IsDBNull(8) ? null : reader.GetInt32(8), + CBigint = reader.IsDBNull(9) ? null : reader.GetInt64(9), + CFloat = reader.IsDBNull(10) ? null : reader.GetDouble(10), + CNumeric = reader.IsDBNull(11) ? null : reader.GetDecimal(11), + CDecimal = reader.IsDBNull(12) ? null : reader.GetDecimal(12), + CDec = reader.IsDBNull(13) ? null : reader.GetDecimal(13), + CFixed = reader.IsDBNull(14) ? null : reader.GetDecimal(14), + CDouble = reader.IsDBNull(15) ? null : reader.GetDouble(15), + CDoublePrecision = reader.IsDBNull(16) ? null : reader.GetDouble(16), + CChar = reader.IsDBNull(17) ? null : reader.GetString(17), + CNchar = reader.IsDBNull(18) ? null : reader.GetString(18), + CNationalChar = reader.IsDBNull(19) ? null : reader.GetString(19), + CVarchar = reader.IsDBNull(20) ? null : reader.GetString(20), + CTinytext = reader.IsDBNull(21) ? null : reader.GetString(21), + CMediumtext = reader.IsDBNull(22) ? null : reader.GetString(22), + CText = reader.IsDBNull(23) ? null : reader.GetString(23), + CLongtext = reader.IsDBNull(24) ? null : reader.GetString(24), + CEnum = reader.IsDBNull(25) ? null : reader.GetString(25).ToMysqlTypesCEnum(), + CYear = reader.IsDBNull(26) ? null : reader.GetInt16(26), + CDate = reader.IsDBNull(27) ? null : reader.GetDateTime(27), + CDatetime = reader.IsDBNull(28) ? null : reader.GetDateTime(28), + CTimestamp = reader.IsDBNull(29) ? null : reader.GetDateTime(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } + } } return null; @@ -589,13 +1110,30 @@ public async Task InsertMysqlTypesBatch(List args) private const string TruncateMysqlTypesSql = "TRUNCATE TABLE mysql_types"; public async Task TruncateMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(TruncateMysqlTypesSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(TruncateMysqlTypesSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncateMysqlTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -603,16 +1141,36 @@ public async Task TruncateMysqlTypes() public readonly record struct CreateExtendedBioArgs(string? AuthorName, string? Name, ExtendedBiosBioType? BioType); public async Task CreateExtendedBio(CreateExtendedBioArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateExtendedBioSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@author_name", args.AuthorName ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@name", args.Name ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateExtendedBioSql, connection)) + { + command.Parameters.AddWithValue("@author_name", args.AuthorName ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@name", args.Name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateExtendedBioSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@author_name", args.AuthorName ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@name", args.Name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -621,25 +1179,54 @@ public async Task CreateExtendedBio(CreateExtendedBioArgs args) public readonly record struct GetFirstExtendedBioByTypeArgs(ExtendedBiosBioType? BioType); public async Task GetFirstExtendedBioByType(GetFirstExtendedBioByTypeArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetFirstExtendedBioByTypeSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetFirstExtendedBioByTypeSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetFirstExtendedBioByTypeRow + if (await reader.ReadAsync()) { - AuthorName = reader.IsDBNull(0) ? null : reader.GetString(0), - Name = reader.IsDBNull(1) ? null : reader.GetString(1), - BioType = reader.IsDBNull(2) ? null : reader.GetString(2).ToExtendedBiosBioType() - }; + return new GetFirstExtendedBioByTypeRow + { + AuthorName = reader.IsDBNull(0) ? null : reader.GetString(0), + Name = reader.IsDBNull(1) ? null : reader.GetString(1), + BioType = reader.IsDBNull(2) ? null : reader.GetString(2).ToExtendedBiosBioType() + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetFirstExtendedBioByTypeSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetFirstExtendedBioByTypeRow + { + AuthorName = reader.IsDBNull(0) ? null : reader.GetString(0), + Name = reader.IsDBNull(1) ? null : reader.GetString(1), + BioType = reader.IsDBNull(2) ? null : reader.GetString(2).ToExtendedBiosBioType() + }; + } + } } return null; @@ -648,13 +1235,30 @@ public async Task CreateExtendedBio(CreateExtendedBioArgs args) private const string TruncateExtendedBiosSql = "TRUNCATE TABLE extended.bios"; public async Task TruncateExtendedBios() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(TruncateExtendedBiosSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(TruncateExtendedBiosSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncateExtendedBiosSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } } \ No newline at end of file diff --git a/examples/MySqlConnectorLegacyExample/QuerySql.cs b/examples/MySqlConnectorLegacyExample/QuerySql.cs index a1199951..ce2a0bf1 100644 --- a/examples/MySqlConnectorLegacyExample/QuerySql.cs +++ b/examples/MySqlConnectorLegacyExample/QuerySql.cs @@ -24,6 +24,12 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } + public QuerySql(MySqlTransaction transaction) + { + this.Transaction = transaction; + } + + private MySqlTransaction Transaction { get; } private string ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; @@ -39,25 +45,54 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -72,21 +107,45 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(ListAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(ListAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -100,16 +159,36 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateAuthorSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateAuthorSql, connection)) + { + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -121,17 +200,35 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateAuthorReturnIdSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - await command.ExecuteNonQueryAsync(); - return command.LastInsertedId; + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateAuthorReturnIdSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorReturnIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -147,25 +244,54 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorByIdSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorByIdSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorByIdRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -184,22 +310,47 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorByNamePatternSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorByNamePatternSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByNamePatternSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -211,27 +362,62 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(DeleteAuthorSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(DeleteAuthorSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); } } private const string DeleteAllAuthorsSql = "DELETE FROM authors"; public async Task DeleteAllAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(DeleteAllAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(DeleteAllAuthorsSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAllAuthorsSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -242,15 +428,31 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(UpdateAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - return await command.ExecuteNonQueryAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(UpdateAuthorsSql, connection)) + { + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = UpdateAuthorsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids)"; @@ -266,25 +468,51 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - using (var command = new MySqlCommand(transformedSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(transformedSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -303,28 +531,56 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - using (var command = new MySqlCommand(transformedSql, connection)) - { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); - using (var reader = await command.ExecuteReaderAsync()) - { - var result = new List(); - while (await reader.ReadAsync()) + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.OpenAsync(); + using (var command = new MySqlCommand(transformedSql, connection)) + { + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -337,17 +593,35 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateBookSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@author_id", args.AuthorId); - await command.ExecuteNonQueryAsync(); - return command.LastInsertedId; + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateBookSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateBookSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + await command.ExecuteNonQueryAsync(); + return command.LastInsertedId; + } } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name "; @@ -358,21 +632,45 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -385,21 +683,45 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -418,22 +740,47 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -479,48 +826,100 @@ public class InsertMysqlTypesArgs }; public async Task InsertMysqlTypes(InsertMysqlTypesArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(InsertMysqlTypesSql, connection)) - { - command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_dec", args.CDec ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_fixed", args.CFixed ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_float", args.CFloat ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_double", args.CDouble ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_nchar", args.CNchar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_national_char", args.CNationalChar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_tinytext", args.CTinytext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_enum", args.CEnum ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_tinyblob", args.CTinyblob ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_mediumblob", args.CMediumblob ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_longblob", args.CLongblob ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + using (var connection = new MySqlConnection(ConnectionString)) + { + await connection.OpenAsync(); + using (var command = new MySqlCommand(InsertMysqlTypesSql, connection)) + { + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_dec", args.CDec ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_fixed", args.CFixed ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_float", args.CFloat ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double", args.CDouble ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_nchar", args.CNchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_national_char", args.CNationalChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinytext", args.CTinytext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_enum", args.CEnum ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyblob", args.CTinyblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumblob", args.CMediumblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longblob", args.CLongblob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertMysqlTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_dec", args.CDec ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_fixed", args.CFixed ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_float", args.CFloat ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double", args.CDouble ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_nchar", args.CNchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_national_char", args.CNationalChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinytext", args.CTinytext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_enum", args.CEnum ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_tinyblob", args.CTinyblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_mediumblob", args.CMediumblob ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_longblob", args.CLongblob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -664,57 +1063,118 @@ public class GetMysqlTypesRow }; public async Task GetMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetMysqlTypesSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetMysqlTypesSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetMysqlTypesRow + if (await reader.ReadAsync()) { - CBool = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), - CBoolean = reader.IsDBNull(1) ? (bool? )null : reader.GetBoolean(1), - CTinyint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2), - CSmallint = reader.IsDBNull(3) ? (short? )null : reader.GetInt16(3), - CMediumint = reader.IsDBNull(4) ? (int? )null : reader.GetInt32(4), - CInt = reader.IsDBNull(5) ? (int? )null : reader.GetInt32(5), - CInteger = reader.IsDBNull(6) ? (int? )null : reader.GetInt32(6), - CBigint = reader.IsDBNull(7) ? (long? )null : reader.GetInt64(7), - CFloat = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), - CDecimal = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), - CDec = reader.IsDBNull(10) ? (decimal? )null : reader.GetDecimal(10), - CNumeric = reader.IsDBNull(11) ? (decimal? )null : reader.GetDecimal(11), - CFixed = reader.IsDBNull(12) ? (decimal? )null : reader.GetDecimal(12), - CDouble = reader.IsDBNull(13) ? (double? )null : reader.GetDouble(13), - CDoublePrecision = reader.IsDBNull(14) ? (double? )null : reader.GetDouble(14), - CYear = reader.IsDBNull(15) ? (short? )null : reader.GetInt16(15), - CDate = reader.IsDBNull(16) ? (DateTime? )null : reader.GetDateTime(16), - CTime = reader.IsDBNull(17) ? null : reader.GetString(17), - CDatetime = reader.IsDBNull(18) ? (DateTime? )null : reader.GetDateTime(18), - CTimestamp = reader.IsDBNull(19) ? (DateTime? )null : reader.GetDateTime(19), - CChar = reader.IsDBNull(20) ? null : reader.GetString(20), - CNchar = reader.IsDBNull(21) ? null : reader.GetString(21), - CNationalChar = reader.IsDBNull(22) ? null : reader.GetString(22), - CVarchar = reader.IsDBNull(23) ? null : reader.GetString(23), - CTinytext = reader.IsDBNull(24) ? null : reader.GetString(24), - CMediumtext = reader.IsDBNull(25) ? null : reader.GetString(25), - CText = reader.IsDBNull(26) ? null : reader.GetString(26), - CLongtext = reader.IsDBNull(27) ? null : reader.GetString(27), - CEnum = reader.IsDBNull(28) ? (MysqlTypesCEnum? )null : reader.GetString(28).ToMysqlTypesCEnum(), - CBit = reader.IsDBNull(29) ? (byte? )null : reader.GetFieldValue(29), - CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), - CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), - CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), - CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), - CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), - CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) - }; + return new GetMysqlTypesRow + { + CBool = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), + CBoolean = reader.IsDBNull(1) ? (bool? )null : reader.GetBoolean(1), + CTinyint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2), + CSmallint = reader.IsDBNull(3) ? (short? )null : reader.GetInt16(3), + CMediumint = reader.IsDBNull(4) ? (int? )null : reader.GetInt32(4), + CInt = reader.IsDBNull(5) ? (int? )null : reader.GetInt32(5), + CInteger = reader.IsDBNull(6) ? (int? )null : reader.GetInt32(6), + CBigint = reader.IsDBNull(7) ? (long? )null : reader.GetInt64(7), + CFloat = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), + CDecimal = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), + CDec = reader.IsDBNull(10) ? (decimal? )null : reader.GetDecimal(10), + CNumeric = reader.IsDBNull(11) ? (decimal? )null : reader.GetDecimal(11), + CFixed = reader.IsDBNull(12) ? (decimal? )null : reader.GetDecimal(12), + CDouble = reader.IsDBNull(13) ? (double? )null : reader.GetDouble(13), + CDoublePrecision = reader.IsDBNull(14) ? (double? )null : reader.GetDouble(14), + CYear = reader.IsDBNull(15) ? (short? )null : reader.GetInt16(15), + CDate = reader.IsDBNull(16) ? (DateTime? )null : reader.GetDateTime(16), + CTime = reader.IsDBNull(17) ? null : reader.GetString(17), + CDatetime = reader.IsDBNull(18) ? (DateTime? )null : reader.GetDateTime(18), + CTimestamp = reader.IsDBNull(19) ? (DateTime? )null : reader.GetDateTime(19), + CChar = reader.IsDBNull(20) ? null : reader.GetString(20), + CNchar = reader.IsDBNull(21) ? null : reader.GetString(21), + CNationalChar = reader.IsDBNull(22) ? null : reader.GetString(22), + CVarchar = reader.IsDBNull(23) ? null : reader.GetString(23), + CTinytext = reader.IsDBNull(24) ? null : reader.GetString(24), + CMediumtext = reader.IsDBNull(25) ? null : reader.GetString(25), + CText = reader.IsDBNull(26) ? null : reader.GetString(26), + CLongtext = reader.IsDBNull(27) ? null : reader.GetString(27), + CEnum = reader.IsDBNull(28) ? (MysqlTypesCEnum? )null : reader.GetString(28).ToMysqlTypesCEnum(), + CBit = reader.IsDBNull(29) ? (byte? )null : reader.GetFieldValue(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetMysqlTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetMysqlTypesRow + { + CBool = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), + CBoolean = reader.IsDBNull(1) ? (bool? )null : reader.GetBoolean(1), + CTinyint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2), + CSmallint = reader.IsDBNull(3) ? (short? )null : reader.GetInt16(3), + CMediumint = reader.IsDBNull(4) ? (int? )null : reader.GetInt32(4), + CInt = reader.IsDBNull(5) ? (int? )null : reader.GetInt32(5), + CInteger = reader.IsDBNull(6) ? (int? )null : reader.GetInt32(6), + CBigint = reader.IsDBNull(7) ? (long? )null : reader.GetInt64(7), + CFloat = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), + CDecimal = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), + CDec = reader.IsDBNull(10) ? (decimal? )null : reader.GetDecimal(10), + CNumeric = reader.IsDBNull(11) ? (decimal? )null : reader.GetDecimal(11), + CFixed = reader.IsDBNull(12) ? (decimal? )null : reader.GetDecimal(12), + CDouble = reader.IsDBNull(13) ? (double? )null : reader.GetDouble(13), + CDoublePrecision = reader.IsDBNull(14) ? (double? )null : reader.GetDouble(14), + CYear = reader.IsDBNull(15) ? (short? )null : reader.GetInt16(15), + CDate = reader.IsDBNull(16) ? (DateTime? )null : reader.GetDateTime(16), + CTime = reader.IsDBNull(17) ? null : reader.GetString(17), + CDatetime = reader.IsDBNull(18) ? (DateTime? )null : reader.GetDateTime(18), + CTimestamp = reader.IsDBNull(19) ? (DateTime? )null : reader.GetDateTime(19), + CChar = reader.IsDBNull(20) ? null : reader.GetString(20), + CNchar = reader.IsDBNull(21) ? null : reader.GetString(21), + CNationalChar = reader.IsDBNull(22) ? null : reader.GetString(22), + CVarchar = reader.IsDBNull(23) ? null : reader.GetString(23), + CTinytext = reader.IsDBNull(24) ? null : reader.GetString(24), + CMediumtext = reader.IsDBNull(25) ? null : reader.GetString(25), + CText = reader.IsDBNull(26) ? null : reader.GetString(26), + CLongtext = reader.IsDBNull(27) ? null : reader.GetString(27), + CEnum = reader.IsDBNull(28) ? (MysqlTypesCEnum? )null : reader.GetString(28).ToMysqlTypesCEnum(), + CBit = reader.IsDBNull(29) ? (byte? )null : reader.GetFieldValue(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } + } } return null; @@ -762,57 +1222,118 @@ public class GetMysqlTypesAggRow }; public async Task GetMysqlTypesAgg() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetMysqlTypesAggSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetMysqlTypesAggSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetMysqlTypesAggRow + if (await reader.ReadAsync()) { - Cnt = reader.GetInt64(0), - CBool = reader.IsDBNull(1) ? (bool? )null : reader.GetBoolean(1), - CBoolean = reader.IsDBNull(2) ? (bool? )null : reader.GetBoolean(2), - CBit = reader.IsDBNull(3) ? (byte? )null : reader.GetFieldValue(3), - CTinyint = reader.IsDBNull(4) ? (short? )null : reader.GetInt16(4), - CSmallint = reader.IsDBNull(5) ? (short? )null : reader.GetInt16(5), - CMediumint = reader.IsDBNull(6) ? (int? )null : reader.GetInt32(6), - CInt = reader.IsDBNull(7) ? (int? )null : reader.GetInt32(7), - CInteger = reader.IsDBNull(8) ? (int? )null : reader.GetInt32(8), - CBigint = reader.IsDBNull(9) ? (long? )null : reader.GetInt64(9), - CFloat = reader.IsDBNull(10) ? (double? )null : reader.GetDouble(10), - CNumeric = reader.IsDBNull(11) ? (decimal? )null : reader.GetDecimal(11), - CDecimal = reader.IsDBNull(12) ? (decimal? )null : reader.GetDecimal(12), - CDec = reader.IsDBNull(13) ? (decimal? )null : reader.GetDecimal(13), - CFixed = reader.IsDBNull(14) ? (decimal? )null : reader.GetDecimal(14), - CDouble = reader.IsDBNull(15) ? (double? )null : reader.GetDouble(15), - CDoublePrecision = reader.IsDBNull(16) ? (double? )null : reader.GetDouble(16), - CChar = reader.IsDBNull(17) ? null : reader.GetString(17), - CNchar = reader.IsDBNull(18) ? null : reader.GetString(18), - CNationalChar = reader.IsDBNull(19) ? null : reader.GetString(19), - CVarchar = reader.IsDBNull(20) ? null : reader.GetString(20), - CTinytext = reader.IsDBNull(21) ? null : reader.GetString(21), - CMediumtext = reader.IsDBNull(22) ? null : reader.GetString(22), - CText = reader.IsDBNull(23) ? null : reader.GetString(23), - CLongtext = reader.IsDBNull(24) ? null : reader.GetString(24), - CEnum = reader.IsDBNull(25) ? (MysqlTypesCEnum? )null : reader.GetString(25).ToMysqlTypesCEnum(), - CYear = reader.IsDBNull(26) ? (short? )null : reader.GetInt16(26), - CDate = reader.IsDBNull(27) ? (DateTime? )null : reader.GetDateTime(27), - CDatetime = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28), - CTimestamp = reader.IsDBNull(29) ? (DateTime? )null : reader.GetDateTime(29), - CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), - CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), - CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), - CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), - CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), - CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) - }; + return new GetMysqlTypesAggRow + { + Cnt = reader.GetInt64(0), + CBool = reader.IsDBNull(1) ? (bool? )null : reader.GetBoolean(1), + CBoolean = reader.IsDBNull(2) ? (bool? )null : reader.GetBoolean(2), + CBit = reader.IsDBNull(3) ? (byte? )null : reader.GetFieldValue(3), + CTinyint = reader.IsDBNull(4) ? (short? )null : reader.GetInt16(4), + CSmallint = reader.IsDBNull(5) ? (short? )null : reader.GetInt16(5), + CMediumint = reader.IsDBNull(6) ? (int? )null : reader.GetInt32(6), + CInt = reader.IsDBNull(7) ? (int? )null : reader.GetInt32(7), + CInteger = reader.IsDBNull(8) ? (int? )null : reader.GetInt32(8), + CBigint = reader.IsDBNull(9) ? (long? )null : reader.GetInt64(9), + CFloat = reader.IsDBNull(10) ? (double? )null : reader.GetDouble(10), + CNumeric = reader.IsDBNull(11) ? (decimal? )null : reader.GetDecimal(11), + CDecimal = reader.IsDBNull(12) ? (decimal? )null : reader.GetDecimal(12), + CDec = reader.IsDBNull(13) ? (decimal? )null : reader.GetDecimal(13), + CFixed = reader.IsDBNull(14) ? (decimal? )null : reader.GetDecimal(14), + CDouble = reader.IsDBNull(15) ? (double? )null : reader.GetDouble(15), + CDoublePrecision = reader.IsDBNull(16) ? (double? )null : reader.GetDouble(16), + CChar = reader.IsDBNull(17) ? null : reader.GetString(17), + CNchar = reader.IsDBNull(18) ? null : reader.GetString(18), + CNationalChar = reader.IsDBNull(19) ? null : reader.GetString(19), + CVarchar = reader.IsDBNull(20) ? null : reader.GetString(20), + CTinytext = reader.IsDBNull(21) ? null : reader.GetString(21), + CMediumtext = reader.IsDBNull(22) ? null : reader.GetString(22), + CText = reader.IsDBNull(23) ? null : reader.GetString(23), + CLongtext = reader.IsDBNull(24) ? null : reader.GetString(24), + CEnum = reader.IsDBNull(25) ? (MysqlTypesCEnum? )null : reader.GetString(25).ToMysqlTypesCEnum(), + CYear = reader.IsDBNull(26) ? (short? )null : reader.GetInt16(26), + CDate = reader.IsDBNull(27) ? (DateTime? )null : reader.GetDateTime(27), + CDatetime = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28), + CTimestamp = reader.IsDBNull(29) ? (DateTime? )null : reader.GetDateTime(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetMysqlTypesAggSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetMysqlTypesAggRow + { + Cnt = reader.GetInt64(0), + CBool = reader.IsDBNull(1) ? (bool? )null : reader.GetBoolean(1), + CBoolean = reader.IsDBNull(2) ? (bool? )null : reader.GetBoolean(2), + CBit = reader.IsDBNull(3) ? (byte? )null : reader.GetFieldValue(3), + CTinyint = reader.IsDBNull(4) ? (short? )null : reader.GetInt16(4), + CSmallint = reader.IsDBNull(5) ? (short? )null : reader.GetInt16(5), + CMediumint = reader.IsDBNull(6) ? (int? )null : reader.GetInt32(6), + CInt = reader.IsDBNull(7) ? (int? )null : reader.GetInt32(7), + CInteger = reader.IsDBNull(8) ? (int? )null : reader.GetInt32(8), + CBigint = reader.IsDBNull(9) ? (long? )null : reader.GetInt64(9), + CFloat = reader.IsDBNull(10) ? (double? )null : reader.GetDouble(10), + CNumeric = reader.IsDBNull(11) ? (decimal? )null : reader.GetDecimal(11), + CDecimal = reader.IsDBNull(12) ? (decimal? )null : reader.GetDecimal(12), + CDec = reader.IsDBNull(13) ? (decimal? )null : reader.GetDecimal(13), + CFixed = reader.IsDBNull(14) ? (decimal? )null : reader.GetDecimal(14), + CDouble = reader.IsDBNull(15) ? (double? )null : reader.GetDouble(15), + CDoublePrecision = reader.IsDBNull(16) ? (double? )null : reader.GetDouble(16), + CChar = reader.IsDBNull(17) ? null : reader.GetString(17), + CNchar = reader.IsDBNull(18) ? null : reader.GetString(18), + CNationalChar = reader.IsDBNull(19) ? null : reader.GetString(19), + CVarchar = reader.IsDBNull(20) ? null : reader.GetString(20), + CTinytext = reader.IsDBNull(21) ? null : reader.GetString(21), + CMediumtext = reader.IsDBNull(22) ? null : reader.GetString(22), + CText = reader.IsDBNull(23) ? null : reader.GetString(23), + CLongtext = reader.IsDBNull(24) ? null : reader.GetString(24), + CEnum = reader.IsDBNull(25) ? (MysqlTypesCEnum? )null : reader.GetString(25).ToMysqlTypesCEnum(), + CYear = reader.IsDBNull(26) ? (short? )null : reader.GetInt16(26), + CDate = reader.IsDBNull(27) ? (DateTime? )null : reader.GetDateTime(27), + CDatetime = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28), + CTimestamp = reader.IsDBNull(29) ? (DateTime? )null : reader.GetDateTime(29), + CBinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CVarbinary = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CTinyblob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CBlob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CMediumblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34), + CLongblob = reader.IsDBNull(35) ? null : reader.GetFieldValue(35) + }; + } + } } return null; @@ -821,13 +1342,30 @@ public async Task GetMysqlTypesAgg() private const string TruncateMysqlTypesSql = "TRUNCATE TABLE mysql_types"; public async Task TruncateMysqlTypes() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(TruncateMysqlTypesSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(TruncateMysqlTypesSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncateMysqlTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -840,16 +1378,36 @@ public class CreateExtendedBioArgs }; public async Task CreateExtendedBio(CreateExtendedBioArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(CreateExtendedBioSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@author_name", args.AuthorName ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@name", args.Name ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(CreateExtendedBioSql, connection)) + { + command.Parameters.AddWithValue("@author_name", args.AuthorName ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@name", args.Name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateExtendedBioSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@author_name", args.AuthorName ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@name", args.Name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -866,25 +1424,54 @@ public class GetFirstExtendedBioByTypeArgs }; public async Task GetFirstExtendedBioByType(GetFirstExtendedBioByTypeArgs args) { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(GetFirstExtendedBioByTypeSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new MySqlCommand(GetFirstExtendedBioByTypeSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetFirstExtendedBioByTypeRow + if (await reader.ReadAsync()) { - AuthorName = reader.IsDBNull(0) ? null : reader.GetString(0), - Name = reader.IsDBNull(1) ? null : reader.GetString(1), - BioType = reader.IsDBNull(2) ? (ExtendedBiosBioType? )null : reader.GetString(2).ToExtendedBiosBioType() - }; + return new GetFirstExtendedBioByTypeRow + { + AuthorName = reader.IsDBNull(0) ? null : reader.GetString(0), + Name = reader.IsDBNull(1) ? null : reader.GetString(1), + BioType = reader.IsDBNull(2) ? (ExtendedBiosBioType? )null : reader.GetString(2).ToExtendedBiosBioType() + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetFirstExtendedBioByTypeSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio_type", args.BioType ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetFirstExtendedBioByTypeRow + { + AuthorName = reader.IsDBNull(0) ? null : reader.GetString(0), + Name = reader.IsDBNull(1) ? null : reader.GetString(1), + BioType = reader.IsDBNull(2) ? (ExtendedBiosBioType? )null : reader.GetString(2).ToExtendedBiosBioType() + }; + } + } } return null; @@ -893,13 +1480,30 @@ public async Task GetFirstExtendedBioByType(GetFir private const string TruncateExtendedBiosSql = "TRUNCATE TABLE extended.bios"; public async Task TruncateExtendedBios() { - using (var connection = new MySqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new MySqlCommand(TruncateExtendedBiosSql, connection)) + using (var connection = new MySqlConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new MySqlCommand(TruncateExtendedBiosSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncateExtendedBiosSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } } diff --git a/examples/NpgsqlDapperExample/QuerySql.cs b/examples/NpgsqlDapperExample/QuerySql.cs index fe6cc961..d9d28a06 100644 --- a/examples/NpgsqlDapperExample/QuerySql.cs +++ b/examples/NpgsqlDapperExample/QuerySql.cs @@ -22,7 +22,15 @@ public QuerySql(string connectionString) Utils.ConfigureSqlMapper(); } - private string ConnectionString { get; } + public QuerySql(NpgsqlTransaction transaction) + { + this.Transaction = transaction; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; + Utils.ConfigureSqlMapper(); + } + + private NpgsqlTransaction? Transaction { get; } + private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; public class GetAuthorRow @@ -37,13 +45,23 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams, transaction: this.Transaction); } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name"; @@ -55,11 +73,21 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(ListAuthorsSql); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryAsync(ListAuthorsSql); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(ListAuthorsSql, transaction: this.Transaction)).AsList(); } private const string CreateAuthorSql = "INSERT INTO authors (id, name, bio) VALUES (@id, @name, @bio) RETURNING id, name, bio"; @@ -77,15 +105,25 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(CreateAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - var result = await connection.QueryFirstOrDefaultAsync(CreateAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(CreateAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio) RETURNING id"; @@ -100,13 +138,23 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -122,13 +170,23 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByNamePatternSql = "SELECT id, name, bio FROM authors WHERE name LIKE COALESCE(@name_pattern, '%')"; @@ -144,13 +202,23 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name_pattern", args.NamePattern); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name_pattern", args.NamePattern); - var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorByNamePatternSql, queryParams, transaction: this.Transaction)).AsList(); } private const string DeleteAuthorSql = "DELETE FROM authors WHERE name = @name"; @@ -160,21 +228,45 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAuthorSql, queryParams, transaction: this.Transaction); } private const string TruncateAuthorsSql = "TRUNCATE TABLE authors CASCADE"; public async Task TruncateAuthors() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncateAuthorsSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(TruncateAuthorsSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(TruncateAuthorsSql, transaction: this.Transaction); } private const string UpdateAuthorsSql = "UPDATE authors SET bio = @bio WHERE bio IS NOT NULL "; @@ -184,12 +276,22 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio", args.Bio); - return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.ExecuteAsync(UpdateAuthorsSql, queryParams, transaction: this.Transaction); } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id = ANY(@longArr_1::BIGINT[])"; @@ -205,13 +307,23 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("longArr_1", args.LongArr1); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorsByIdsSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("longArr_1", args.LongArr1); - var result = await connection.QueryAsync(GetAuthorsByIdsSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorsByIdsSql, queryParams, transaction: this.Transaction)).AsList(); } private const string GetAuthorsByIdsAndNamesSql = "SELECT id, name, bio FROM authors WHERE id = ANY(@longArr_1::BIGINT[]) AND name = ANY(@stringArr_2::TEXT[])"; @@ -228,14 +340,24 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("longArr_1", args.LongArr1); + queryParams.Add("stringArr_2", args.StringArr2); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorsByIdsAndNamesSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("longArr_1", args.LongArr1); - queryParams.Add("stringArr_2", args.StringArr2); - var result = await connection.QueryAsync(GetAuthorsByIdsAndNamesSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorsByIdsAndNamesSql, queryParams, transaction: this.Transaction)).AsList(); } private const string CreateBookSql = "INSERT INTO books (name, author_id) VALUES (@name, @author_id) RETURNING id"; @@ -250,13 +372,23 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("author_id", args.AuthorId); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateBookSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("author_id", args.AuthorId); - return await connection.QuerySingleAsync(CreateBookSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateBookSql, queryParams, transaction: this.Transaction); } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors.id = books.author_id ORDER BY authors.name"; @@ -267,20 +399,44 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -293,20 +449,44 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -325,21 +505,46 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -371,32 +576,44 @@ public class InsertPostgresTypesArgs }; public async Task InsertPostgresTypes(InsertPostgresTypesArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) - { - var queryParams = new Dictionary(); - queryParams.Add("c_boolean", args.CBoolean); - queryParams.Add("c_bit", args.CBit); - queryParams.Add("c_smallint", args.CSmallint); - queryParams.Add("c_integer", args.CInteger); - queryParams.Add("c_bigint", args.CBigint); - queryParams.Add("c_real", args.CReal); - queryParams.Add("c_numeric", args.CNumeric); - queryParams.Add("c_decimal", args.CDecimal); - queryParams.Add("c_double_precision", args.CDoublePrecision); - queryParams.Add("c_money", args.CMoney); - queryParams.Add("c_date", args.CDate); - queryParams.Add("c_time", args.CTime); - queryParams.Add("c_timestamp", args.CTimestamp); - queryParams.Add("c_timestamp_with_tz", args.CTimestampWithTz); - queryParams.Add("c_char", args.CChar); - queryParams.Add("c_varchar", args.CVarchar); - queryParams.Add("c_character_varying", args.CCharacterVarying); - queryParams.Add("c_text", args.CText); - queryParams.Add("c_bytea", args.CBytea); - queryParams.Add("c_text_array", args.CTextArray); - queryParams.Add("c_integer_array", args.CIntegerArray); - await connection.ExecuteAsync(InsertPostgresTypesSql, queryParams); + var queryParams = new Dictionary(); + queryParams.Add("c_boolean", args.CBoolean); + queryParams.Add("c_bit", args.CBit); + queryParams.Add("c_smallint", args.CSmallint); + queryParams.Add("c_integer", args.CInteger); + queryParams.Add("c_bigint", args.CBigint); + queryParams.Add("c_real", args.CReal); + queryParams.Add("c_numeric", args.CNumeric); + queryParams.Add("c_decimal", args.CDecimal); + queryParams.Add("c_double_precision", args.CDoublePrecision); + queryParams.Add("c_money", args.CMoney); + queryParams.Add("c_date", args.CDate); + queryParams.Add("c_time", args.CTime); + queryParams.Add("c_timestamp", args.CTimestamp); + queryParams.Add("c_timestamp_with_tz", args.CTimestampWithTz); + queryParams.Add("c_char", args.CChar); + queryParams.Add("c_varchar", args.CVarchar); + queryParams.Add("c_character_varying", args.CCharacterVarying); + queryParams.Add("c_text", args.CText); + queryParams.Add("c_bytea", args.CBytea); + queryParams.Add("c_text_array", args.CTextArray); + queryParams.Add("c_integer_array", args.CIntegerArray); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertPostgresTypesSql, queryParams); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(InsertPostgresTypesSql, queryParams, transaction: this.Transaction); } private const string InsertPostgresTypesBatchSql = "COPY postgres_types (c_boolean, c_smallint, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_char, c_varchar, c_character_varying, c_text, c_bytea) FROM STDIN (FORMAT BINARY)"; @@ -487,11 +704,21 @@ public class GetPostgresTypesRow }; public async Task GetPostgresTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesSql); - return result; + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetPostgresTypesSql, transaction: this.Transaction); } private const string GetPostgresTypesAggSql = "SELECT COUNT(1) AS cnt , c_smallint , c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_char, c_varchar, c_character_varying, c_text, c_bytea FROM postgres_types GROUP BY c_smallint , c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_char, c_varchar, c_character_varying, c_text, c_bytea LIMIT 1 "; @@ -519,11 +746,21 @@ public class GetPostgresTypesAggRow }; public async Task GetPostgresTypesAgg() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesAggSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesAggSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetPostgresTypesAggSql, transaction: this.Transaction); } private const string InsertPostgresGeoTypesSql = "INSERT INTO postgres_geometric_types (c_point, c_line, c_lseg, c_box, c_path, c_polygon, c_circle) VALUES ( @c_point , @c_line, @c_lseg, @c_box, @c_path, @c_polygon, @c_circle ) "; @@ -539,18 +776,30 @@ public class InsertPostgresGeoTypesArgs }; public async Task InsertPostgresGeoTypes(InsertPostgresGeoTypesArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("c_point", args.CPoint); + queryParams.Add("c_line", args.CLine); + queryParams.Add("c_lseg", args.CLseg); + queryParams.Add("c_box", args.CBox); + queryParams.Add("c_path", args.CPath); + queryParams.Add("c_polygon", args.CPolygon); + queryParams.Add("c_circle", args.CCircle); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertPostgresGeoTypesSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("c_point", args.CPoint); - queryParams.Add("c_line", args.CLine); - queryParams.Add("c_lseg", args.CLseg); - queryParams.Add("c_box", args.CBox); - queryParams.Add("c_path", args.CPath); - queryParams.Add("c_polygon", args.CPolygon); - queryParams.Add("c_circle", args.CCircle); - await connection.ExecuteAsync(InsertPostgresGeoTypesSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(InsertPostgresGeoTypesSql, queryParams, transaction: this.Transaction); } private const string GetPostgresGeoTypesSql = "SELECT c_point, c_line, c_lseg, c_box, c_path, c_polygon, c_circle FROM postgres_geometric_types LIMIT 1"; @@ -566,28 +815,62 @@ public class GetPostgresGeoTypesRow }; public async Task GetPostgresGeoTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - var result = await connection.QueryFirstOrDefaultAsync(GetPostgresGeoTypesSql); - return result; + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetPostgresGeoTypesSql); + return result; + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetPostgresGeoTypesSql, transaction: this.Transaction); } private const string TruncatePostgresTypesSql = "TRUNCATE TABLE postgres_types"; public async Task TruncatePostgresTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncatePostgresTypesSql); + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncatePostgresTypesSql); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(TruncatePostgresTypesSql, transaction: this.Transaction); } private const string TruncatePostgresGeoTypesSql = "TRUNCATE TABLE postgres_geometric_types"; public async Task TruncatePostgresGeoTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncatePostgresGeoTypesSql); + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncatePostgresGeoTypesSql); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(TruncatePostgresGeoTypesSql, transaction: this.Transaction); } } \ No newline at end of file diff --git a/examples/NpgsqlDapperLegacyExample/QuerySql.cs b/examples/NpgsqlDapperLegacyExample/QuerySql.cs index eeed396d..e0a4d1c5 100644 --- a/examples/NpgsqlDapperLegacyExample/QuerySql.cs +++ b/examples/NpgsqlDapperLegacyExample/QuerySql.cs @@ -23,6 +23,14 @@ public QuerySql(string connectionString) Utils.ConfigureSqlMapper(); } + public QuerySql(NpgsqlTransaction transaction) + { + this.Transaction = transaction; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; + Utils.ConfigureSqlMapper(); + } + + private NpgsqlTransaction Transaction { get; } private string ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; @@ -38,13 +46,23 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams, transaction: this.Transaction); } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name"; @@ -56,11 +74,21 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(ListAuthorsSql); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryAsync(ListAuthorsSql); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(ListAuthorsSql, transaction: this.Transaction)).AsList(); } private const string CreateAuthorSql = "INSERT INTO authors (id, name, bio) VALUES (@id, @name, @bio) RETURNING id, name, bio"; @@ -78,15 +106,25 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(CreateAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - var result = await connection.QueryFirstOrDefaultAsync(CreateAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(CreateAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio) RETURNING id"; @@ -101,13 +139,23 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -123,13 +171,23 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByNamePatternSql = "SELECT id, name, bio FROM authors WHERE name LIKE COALESCE(@name_pattern, '%')"; @@ -145,13 +203,23 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name_pattern", args.NamePattern); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name_pattern", args.NamePattern); - var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorByNamePatternSql, queryParams, transaction: this.Transaction)).AsList(); } private const string DeleteAuthorSql = "DELETE FROM authors WHERE name = @name"; @@ -161,21 +229,45 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAuthorSql, queryParams, transaction: this.Transaction); } private const string TruncateAuthorsSql = "TRUNCATE TABLE authors CASCADE"; public async Task TruncateAuthors() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncateAuthorsSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(TruncateAuthorsSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(TruncateAuthorsSql, transaction: this.Transaction); } private const string UpdateAuthorsSql = "UPDATE authors SET bio = @bio WHERE bio IS NOT NULL "; @@ -185,12 +277,22 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio", args.Bio); - return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.ExecuteAsync(UpdateAuthorsSql, queryParams, transaction: this.Transaction); } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id = ANY(@longArr_1::BIGINT[])"; @@ -206,13 +308,23 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("longArr_1", args.LongArr1); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorsByIdsSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("longArr_1", args.LongArr1); - var result = await connection.QueryAsync(GetAuthorsByIdsSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorsByIdsSql, queryParams, transaction: this.Transaction)).AsList(); } private const string GetAuthorsByIdsAndNamesSql = "SELECT id, name, bio FROM authors WHERE id = ANY(@longArr_1::BIGINT[]) AND name = ANY(@stringArr_2::TEXT[])"; @@ -229,14 +341,24 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("longArr_1", args.LongArr1); + queryParams.Add("stringArr_2", args.StringArr2); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorsByIdsAndNamesSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("longArr_1", args.LongArr1); - queryParams.Add("stringArr_2", args.StringArr2); - var result = await connection.QueryAsync(GetAuthorsByIdsAndNamesSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorsByIdsAndNamesSql, queryParams, transaction: this.Transaction)).AsList(); } private const string CreateBookSql = "INSERT INTO books (name, author_id) VALUES (@name, @author_id) RETURNING id"; @@ -251,13 +373,23 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("author_id", args.AuthorId); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateBookSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("author_id", args.AuthorId); - return await connection.QuerySingleAsync(CreateBookSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateBookSql, queryParams, transaction: this.Transaction); } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors.id = books.author_id ORDER BY authors.name"; @@ -268,20 +400,44 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -294,20 +450,44 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -326,21 +506,46 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -372,32 +577,44 @@ public class InsertPostgresTypesArgs }; public async Task InsertPostgresTypes(InsertPostgresTypesArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) - { - var queryParams = new Dictionary(); - queryParams.Add("c_boolean", args.CBoolean); - queryParams.Add("c_bit", args.CBit); - queryParams.Add("c_smallint", args.CSmallint); - queryParams.Add("c_integer", args.CInteger); - queryParams.Add("c_bigint", args.CBigint); - queryParams.Add("c_real", args.CReal); - queryParams.Add("c_numeric", args.CNumeric); - queryParams.Add("c_decimal", args.CDecimal); - queryParams.Add("c_double_precision", args.CDoublePrecision); - queryParams.Add("c_money", args.CMoney); - queryParams.Add("c_date", args.CDate); - queryParams.Add("c_time", args.CTime); - queryParams.Add("c_timestamp", args.CTimestamp); - queryParams.Add("c_timestamp_with_tz", args.CTimestampWithTz); - queryParams.Add("c_char", args.CChar); - queryParams.Add("c_varchar", args.CVarchar); - queryParams.Add("c_character_varying", args.CCharacterVarying); - queryParams.Add("c_text", args.CText); - queryParams.Add("c_bytea", args.CBytea); - queryParams.Add("c_text_array", args.CTextArray); - queryParams.Add("c_integer_array", args.CIntegerArray); - await connection.ExecuteAsync(InsertPostgresTypesSql, queryParams); + var queryParams = new Dictionary(); + queryParams.Add("c_boolean", args.CBoolean); + queryParams.Add("c_bit", args.CBit); + queryParams.Add("c_smallint", args.CSmallint); + queryParams.Add("c_integer", args.CInteger); + queryParams.Add("c_bigint", args.CBigint); + queryParams.Add("c_real", args.CReal); + queryParams.Add("c_numeric", args.CNumeric); + queryParams.Add("c_decimal", args.CDecimal); + queryParams.Add("c_double_precision", args.CDoublePrecision); + queryParams.Add("c_money", args.CMoney); + queryParams.Add("c_date", args.CDate); + queryParams.Add("c_time", args.CTime); + queryParams.Add("c_timestamp", args.CTimestamp); + queryParams.Add("c_timestamp_with_tz", args.CTimestampWithTz); + queryParams.Add("c_char", args.CChar); + queryParams.Add("c_varchar", args.CVarchar); + queryParams.Add("c_character_varying", args.CCharacterVarying); + queryParams.Add("c_text", args.CText); + queryParams.Add("c_bytea", args.CBytea); + queryParams.Add("c_text_array", args.CTextArray); + queryParams.Add("c_integer_array", args.CIntegerArray); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertPostgresTypesSql, queryParams); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(InsertPostgresTypesSql, queryParams, transaction: this.Transaction); } private const string InsertPostgresTypesBatchSql = "COPY postgres_types (c_boolean, c_smallint, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_char, c_varchar, c_character_varying, c_text, c_bytea) FROM STDIN (FORMAT BINARY)"; @@ -488,11 +705,21 @@ public class GetPostgresTypesRow }; public async Task GetPostgresTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesSql); - return result; + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetPostgresTypesSql, transaction: this.Transaction); } private const string GetPostgresTypesAggSql = "SELECT COUNT(1) AS cnt , c_smallint , c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_char, c_varchar, c_character_varying, c_text, c_bytea FROM postgres_types GROUP BY c_smallint , c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_char, c_varchar, c_character_varying, c_text, c_bytea LIMIT 1 "; @@ -520,11 +747,21 @@ public class GetPostgresTypesAggRow }; public async Task GetPostgresTypesAgg() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesAggSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetPostgresTypesAggSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetPostgresTypesAggSql, transaction: this.Transaction); } private const string InsertPostgresGeoTypesSql = "INSERT INTO postgres_geometric_types (c_point, c_line, c_lseg, c_box, c_path, c_polygon, c_circle) VALUES ( @c_point , @c_line, @c_lseg, @c_box, @c_path, @c_polygon, @c_circle ) "; @@ -540,18 +777,30 @@ public class InsertPostgresGeoTypesArgs }; public async Task InsertPostgresGeoTypes(InsertPostgresGeoTypesArgs args) { - using (var connection = new NpgsqlConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("c_point", args.CPoint); + queryParams.Add("c_line", args.CLine); + queryParams.Add("c_lseg", args.CLseg); + queryParams.Add("c_box", args.CBox); + queryParams.Add("c_path", args.CPath); + queryParams.Add("c_polygon", args.CPolygon); + queryParams.Add("c_circle", args.CCircle); + if (this.Transaction == null) + { + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertPostgresGeoTypesSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("c_point", args.CPoint); - queryParams.Add("c_line", args.CLine); - queryParams.Add("c_lseg", args.CLseg); - queryParams.Add("c_box", args.CBox); - queryParams.Add("c_path", args.CPath); - queryParams.Add("c_polygon", args.CPolygon); - queryParams.Add("c_circle", args.CCircle); - await connection.ExecuteAsync(InsertPostgresGeoTypesSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(InsertPostgresGeoTypesSql, queryParams, transaction: this.Transaction); } private const string GetPostgresGeoTypesSql = "SELECT c_point, c_line, c_lseg, c_box, c_path, c_polygon, c_circle FROM postgres_geometric_types LIMIT 1"; @@ -567,29 +816,63 @@ public class GetPostgresGeoTypesRow }; public async Task GetPostgresGeoTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - var result = await connection.QueryFirstOrDefaultAsync(GetPostgresGeoTypesSql); - return result; + using (var connection = new NpgsqlConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetPostgresGeoTypesSql); + return result; + } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetPostgresGeoTypesSql, transaction: this.Transaction); } private const string TruncatePostgresTypesSql = "TRUNCATE TABLE postgres_types"; public async Task TruncatePostgresTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncatePostgresTypesSql); + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncatePostgresTypesSql); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(TruncatePostgresTypesSql, transaction: this.Transaction); } private const string TruncatePostgresGeoTypesSql = "TRUNCATE TABLE postgres_geometric_types"; public async Task TruncatePostgresGeoTypes() { - using (var connection = new NpgsqlConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.ExecuteAsync(TruncatePostgresGeoTypesSql); + using (var connection = new NpgsqlConnection(ConnectionString)) + { + await connection.ExecuteAsync(TruncatePostgresGeoTypesSql); + } + + return; } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + await this.Transaction.Connection.ExecuteAsync(TruncatePostgresGeoTypesSql, transaction: this.Transaction); } } } \ No newline at end of file diff --git a/examples/NpgsqlExample/QuerySql.cs b/examples/NpgsqlExample/QuerySql.cs index 2d0e1c7a..490fd2c3 100644 --- a/examples/NpgsqlExample/QuerySql.cs +++ b/examples/NpgsqlExample/QuerySql.cs @@ -19,31 +19,66 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - private string ConnectionString { get; } + public QuerySql(NpgsqlTransaction transaction) + { + this.Transaction = transaction; + } + + private NpgsqlTransaction? Transaction { get; } + private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; public readonly record struct GetAuthorRow(long Id, string Name, string? Bio); public readonly record struct GetAuthorArgs(string Name); public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorSql)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -53,20 +88,44 @@ public QuerySql(string connectionString) public readonly record struct ListAuthorsRow(long Id, string Name, string? Bio); public async Task> ListAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(ListAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(ListAuthorsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -76,26 +135,57 @@ public async Task> ListAuthors() public readonly record struct CreateAuthorArgs(long Id, string Name, string? Bio); public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(CreateAuthorSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(CreateAuthorSql)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - return new CreateAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new CreateAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new CreateAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -106,16 +196,34 @@ public async Task> ListAuthors() public readonly record struct CreateAuthorReturnIdArgs(string Name, string? Bio); public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(CreateAuthorReturnIdSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt64(result); + using (var command = connection.CreateCommand(CreateAuthorReturnIdSql)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorReturnIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -123,24 +231,53 @@ public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) public readonly record struct GetAuthorByIdArgs(long Id); public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorByIdSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorByIdSql)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorByIdRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -151,21 +288,46 @@ public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) public readonly record struct GetAuthorByNamePatternArgs(string? NamePattern); public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorByNamePatternSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorByNamePatternSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByNamePatternSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -174,25 +336,60 @@ public async Task> GetAuthorByNamePattern(GetAut public readonly record struct DeleteAuthorArgs(string Name); public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(DeleteAuthorSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(DeleteAuthorSql)) + { + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); } } private const string TruncateAuthorsSql = "TRUNCATE TABLE authors CASCADE"; public async Task TruncateAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(TruncateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(TruncateAuthorsSql)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncateAuthorsSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -200,14 +397,30 @@ public async Task TruncateAuthors() public readonly record struct UpdateAuthorsArgs(string? Bio); public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(UpdateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - return await command.ExecuteNonQueryAsync(); + using (var command = connection.CreateCommand(UpdateAuthorsSql)) + { + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = UpdateAuthorsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id = ANY(@longArr_1::BIGINT[])"; @@ -215,21 +428,46 @@ public async Task UpdateAuthors(UpdateAuthorsArgs args) public readonly record struct GetAuthorsByIdsArgs(long[] LongArr1); public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByIdsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@longArr_1", args.LongArr1); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByIdsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByIdsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -239,22 +477,48 @@ public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs public readonly record struct GetAuthorsByIdsAndNamesArgs(long[] LongArr1, string[] StringArr2); public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByIdsAndNamesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@longArr_1", args.LongArr1); - command.Parameters.AddWithValue("@stringArr_2", args.StringArr2); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByIdsAndNamesSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + command.Parameters.AddWithValue("@stringArr_2", args.StringArr2); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByIdsAndNamesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + command.Parameters.AddWithValue("@stringArr_2", args.StringArr2); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -264,36 +528,78 @@ public async Task> GetAuthorsByIdsAndNames(GetA public readonly record struct CreateBookArgs(string Name, long AuthorId); public async Task CreateBook(CreateBookArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(CreateBookSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@author_id", args.AuthorId); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt64(result); + using (var command = connection.CreateCommand(CreateBookSql)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateBookSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors.id = books.author_id ORDER BY authors.name"; public readonly record struct ListAllAuthorsBooksRow(Author? Author, Book? Book); public async Task> ListAllAuthorsBooks() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -302,20 +608,44 @@ public async Task> ListAllAuthorsBooks() public readonly record struct GetDuplicateAuthorsRow(Author? Author, Author? Author2); public async Task> GetDuplicateAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -325,21 +655,46 @@ public async Task> GetDuplicateAuthors() public readonly record struct GetAuthorsByBookNameArgs(string Name); public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -348,33 +703,71 @@ public async Task> GetAuthorsByBookName(GetAuthors public readonly record struct InsertPostgresTypesArgs(bool? CBoolean, byte[]? CBit, short? CSmallint, int? CInteger, long? CBigint, float? CReal, decimal? CNumeric, decimal? CDecimal, double? CDoublePrecision, decimal? CMoney, DateTime? CDate, TimeSpan? CTime, DateTime? CTimestamp, DateTime? CTimestampWithTz, string? CChar, string? CVarchar, string? CCharacterVarying, string? CText, byte[]? CBytea, string[]? CTextArray, int[]? CIntegerArray); public async Task InsertPostgresTypes(InsertPostgresTypesArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) - { - using (var command = connection.CreateCommand(InsertPostgresTypesSql)) - { - command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_money", args.CMoney ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_time", args.CTime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_timestamp_with_tz", args.CTimestampWithTz ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_character_varying", args.CCharacterVarying ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bytea", args.CBytea ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text_array", args.CTextArray ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_integer_array", args.CIntegerArray ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + if (this.Transaction == null) + { + using (var connection = NpgsqlDataSource.Create(ConnectionString)) + { + using (var command = connection.CreateCommand(InsertPostgresTypesSql)) + { + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_money", args.CMoney ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_time", args.CTime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp_with_tz", args.CTimestampWithTz ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_character_varying", args.CCharacterVarying ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bytea", args.CBytea ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text_array", args.CTextArray ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer_array", args.CIntegerArray ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertPostgresTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_money", args.CMoney ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_time", args.CTime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp_with_tz", args.CTimestampWithTz ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_character_varying", args.CCharacterVarying ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bytea", args.CBytea ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text_array", args.CTextArray ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer_array", args.CIntegerArray ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -422,42 +815,89 @@ public async Task InsertPostgresTypesBatch(List ar public readonly record struct GetPostgresTypesRow(bool? CBoolean, byte[]? CBit, short? CSmallint, int? CInteger, long? CBigint, decimal? CDecimal, decimal? CNumeric, float? CReal, double? CDoublePrecision, decimal? CMoney, DateTime? CDate, TimeSpan? CTime, DateTime? CTimestamp, DateTime? CTimestampWithTz, string? CChar, string? CVarchar, string? CCharacterVarying, byte[]? CBytea, string? CText, object? CJson, string[]? CTextArray, int[]? CIntegerArray); public async Task GetPostgresTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetPostgresTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetPostgresTypesSql)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetPostgresTypesRow + if (await reader.ReadAsync()) { - CBoolean = reader.IsDBNull(0) ? null : reader.GetBoolean(0), - CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), - CSmallint = reader.IsDBNull(2) ? null : reader.GetInt16(2), - CInteger = reader.IsDBNull(3) ? null : reader.GetInt32(3), - CBigint = reader.IsDBNull(4) ? null : reader.GetInt64(4), - CDecimal = reader.IsDBNull(5) ? null : reader.GetDecimal(5), - CNumeric = reader.IsDBNull(6) ? null : reader.GetDecimal(6), - CReal = reader.IsDBNull(7) ? null : reader.GetFloat(7), - CDoublePrecision = reader.IsDBNull(8) ? null : reader.GetDouble(8), - CMoney = reader.IsDBNull(9) ? null : reader.GetDecimal(9), - CDate = reader.IsDBNull(10) ? null : reader.GetDateTime(10), - CTime = reader.IsDBNull(11) ? null : reader.GetFieldValue(11), - CTimestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12), - CTimestampWithTz = reader.IsDBNull(13) ? null : reader.GetDateTime(13), - CChar = reader.IsDBNull(14) ? null : reader.GetString(14), - CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), - CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), - CBytea = reader.IsDBNull(17) ? null : reader.GetFieldValue(17), - CText = reader.IsDBNull(18) ? null : reader.GetString(18), - CJson = reader.IsDBNull(19) ? null : reader.GetString(19), - CTextArray = reader.IsDBNull(20) ? null : reader.GetFieldValue(20), - CIntegerArray = reader.IsDBNull(21) ? null : reader.GetFieldValue(21) - }; + return new GetPostgresTypesRow + { + CBoolean = reader.IsDBNull(0) ? null : reader.GetBoolean(0), + CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CSmallint = reader.IsDBNull(2) ? null : reader.GetInt16(2), + CInteger = reader.IsDBNull(3) ? null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? null : reader.GetInt64(4), + CDecimal = reader.IsDBNull(5) ? null : reader.GetDecimal(5), + CNumeric = reader.IsDBNull(6) ? null : reader.GetDecimal(6), + CReal = reader.IsDBNull(7) ? null : reader.GetFloat(7), + CDoublePrecision = reader.IsDBNull(8) ? null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CBytea = reader.IsDBNull(17) ? null : reader.GetFieldValue(17), + CText = reader.IsDBNull(18) ? null : reader.GetString(18), + CJson = reader.IsDBNull(19) ? null : reader.GetString(19), + CTextArray = reader.IsDBNull(20) ? null : reader.GetFieldValue(20), + CIntegerArray = reader.IsDBNull(21) ? null : reader.GetFieldValue(21) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetPostgresTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetPostgresTypesRow + { + CBoolean = reader.IsDBNull(0) ? null : reader.GetBoolean(0), + CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CSmallint = reader.IsDBNull(2) ? null : reader.GetInt16(2), + CInteger = reader.IsDBNull(3) ? null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? null : reader.GetInt64(4), + CDecimal = reader.IsDBNull(5) ? null : reader.GetDecimal(5), + CNumeric = reader.IsDBNull(6) ? null : reader.GetDecimal(6), + CReal = reader.IsDBNull(7) ? null : reader.GetFloat(7), + CDoublePrecision = reader.IsDBNull(8) ? null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CBytea = reader.IsDBNull(17) ? null : reader.GetFieldValue(17), + CText = reader.IsDBNull(18) ? null : reader.GetString(18), + CJson = reader.IsDBNull(19) ? null : reader.GetString(19), + CTextArray = reader.IsDBNull(20) ? null : reader.GetFieldValue(20), + CIntegerArray = reader.IsDBNull(21) ? null : reader.GetFieldValue(21) + }; + } + } } return null; @@ -467,39 +907,83 @@ public async Task InsertPostgresTypesBatch(List ar public readonly record struct GetPostgresTypesAggRow(long Cnt, short? CSmallint, bool? CBoolean, int? CInteger, long? CBigint, float? CReal, decimal? CNumeric, decimal? CDecimal, double? CDoublePrecision, decimal? CMoney, DateTime? CDate, TimeSpan? CTime, DateTime? CTimestamp, DateTime? CTimestampWithTz, string? CChar, string? CVarchar, string? CCharacterVarying, string? CText, byte[]? CBytea); public async Task GetPostgresTypesAgg() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetPostgresTypesAggSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetPostgresTypesAggSql)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetPostgresTypesAggRow + if (await reader.ReadAsync()) { - Cnt = reader.GetInt64(0), - CSmallint = reader.IsDBNull(1) ? null : reader.GetInt16(1), - CBoolean = reader.IsDBNull(2) ? null : reader.GetBoolean(2), - CInteger = reader.IsDBNull(3) ? null : reader.GetInt32(3), - CBigint = reader.IsDBNull(4) ? null : reader.GetInt64(4), - CReal = reader.IsDBNull(5) ? null : reader.GetFloat(5), - CNumeric = reader.IsDBNull(6) ? null : reader.GetDecimal(6), - CDecimal = reader.IsDBNull(7) ? null : reader.GetDecimal(7), - CDoublePrecision = reader.IsDBNull(8) ? null : reader.GetDouble(8), - CMoney = reader.IsDBNull(9) ? null : reader.GetDecimal(9), - CDate = reader.IsDBNull(10) ? null : reader.GetDateTime(10), - CTime = reader.IsDBNull(11) ? null : reader.GetFieldValue(11), - CTimestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12), - CTimestampWithTz = reader.IsDBNull(13) ? null : reader.GetDateTime(13), - CChar = reader.IsDBNull(14) ? null : reader.GetString(14), - CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), - CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), - CText = reader.IsDBNull(17) ? null : reader.GetString(17), - CBytea = reader.IsDBNull(18) ? null : reader.GetFieldValue(18) - }; + return new GetPostgresTypesAggRow + { + Cnt = reader.GetInt64(0), + CSmallint = reader.IsDBNull(1) ? null : reader.GetInt16(1), + CBoolean = reader.IsDBNull(2) ? null : reader.GetBoolean(2), + CInteger = reader.IsDBNull(3) ? null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? null : reader.GetInt64(4), + CReal = reader.IsDBNull(5) ? null : reader.GetFloat(5), + CNumeric = reader.IsDBNull(6) ? null : reader.GetDecimal(6), + CDecimal = reader.IsDBNull(7) ? null : reader.GetDecimal(7), + CDoublePrecision = reader.IsDBNull(8) ? null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CText = reader.IsDBNull(17) ? null : reader.GetString(17), + CBytea = reader.IsDBNull(18) ? null : reader.GetFieldValue(18) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetPostgresTypesAggSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetPostgresTypesAggRow + { + Cnt = reader.GetInt64(0), + CSmallint = reader.IsDBNull(1) ? null : reader.GetInt16(1), + CBoolean = reader.IsDBNull(2) ? null : reader.GetBoolean(2), + CInteger = reader.IsDBNull(3) ? null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? null : reader.GetInt64(4), + CReal = reader.IsDBNull(5) ? null : reader.GetFloat(5), + CNumeric = reader.IsDBNull(6) ? null : reader.GetDecimal(6), + CDecimal = reader.IsDBNull(7) ? null : reader.GetDecimal(7), + CDoublePrecision = reader.IsDBNull(8) ? null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CText = reader.IsDBNull(17) ? null : reader.GetString(17), + CBytea = reader.IsDBNull(18) ? null : reader.GetFieldValue(18) + }; + } + } } return null; @@ -509,19 +993,43 @@ public async Task InsertPostgresTypesBatch(List ar public readonly record struct InsertPostgresGeoTypesArgs(NpgsqlPoint? CPoint, NpgsqlLine? CLine, NpgsqlLSeg? CLseg, NpgsqlBox? CBox, NpgsqlPath? CPath, NpgsqlPolygon? CPolygon, NpgsqlCircle? CCircle); public async Task InsertPostgresGeoTypes(InsertPostgresGeoTypesArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(InsertPostgresGeoTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@c_point", args.CPoint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_line", args.CLine ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_lseg", args.CLseg ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_box", args.CBox ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_path", args.CPath ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_polygon", args.CPolygon ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_circle", args.CCircle ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(InsertPostgresGeoTypesSql)) + { + command.Parameters.AddWithValue("@c_point", args.CPoint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_line", args.CLine ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_lseg", args.CLseg ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_box", args.CBox ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_path", args.CPath ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_polygon", args.CPolygon ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_circle", args.CCircle ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertPostgresGeoTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_point", args.CPoint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_line", args.CLine ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_lseg", args.CLseg ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_box", args.CBox ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_path", args.CPath ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_polygon", args.CPolygon ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_circle", args.CCircle ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -529,27 +1037,59 @@ public async Task InsertPostgresGeoTypes(InsertPostgresGeoTypesArgs args) public readonly record struct GetPostgresGeoTypesRow(NpgsqlPoint? CPoint, NpgsqlLine? CLine, NpgsqlLSeg? CLseg, NpgsqlBox? CBox, NpgsqlPath? CPath, NpgsqlPolygon? CPolygon, NpgsqlCircle? CCircle); public async Task GetPostgresGeoTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetPostgresGeoTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetPostgresGeoTypesSql)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetPostgresGeoTypesRow + if (await reader.ReadAsync()) { - CPoint = reader.IsDBNull(0) ? null : reader.GetFieldValue(0), - CLine = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), - CLseg = reader.IsDBNull(2) ? null : reader.GetFieldValue(2), - CBox = reader.IsDBNull(3) ? null : reader.GetFieldValue(3), - CPath = reader.IsDBNull(4) ? null : reader.GetFieldValue(4), - CPolygon = reader.IsDBNull(5) ? null : reader.GetFieldValue(5), - CCircle = reader.IsDBNull(6) ? null : reader.GetFieldValue(6) - }; + return new GetPostgresGeoTypesRow + { + CPoint = reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + CLine = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CLseg = reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + CBox = reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + CPath = reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + CPolygon = reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + CCircle = reader.IsDBNull(6) ? null : reader.GetFieldValue(6) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetPostgresGeoTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetPostgresGeoTypesRow + { + CPoint = reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + CLine = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CLseg = reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + CBox = reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + CPath = reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + CPolygon = reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + CCircle = reader.IsDBNull(6) ? null : reader.GetFieldValue(6) + }; + } + } } return null; @@ -558,24 +1098,58 @@ public async Task InsertPostgresGeoTypes(InsertPostgresGeoTypesArgs args) private const string TruncatePostgresTypesSql = "TRUNCATE TABLE postgres_types"; public async Task TruncatePostgresTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(TruncatePostgresTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(TruncatePostgresTypesSql)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncatePostgresTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } private const string TruncatePostgresGeoTypesSql = "TRUNCATE TABLE postgres_geometric_types"; public async Task TruncatePostgresGeoTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(TruncatePostgresGeoTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(TruncatePostgresGeoTypesSql)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncatePostgresGeoTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } } \ No newline at end of file diff --git a/examples/NpgsqlLegacyExample/QuerySql.cs b/examples/NpgsqlLegacyExample/QuerySql.cs index 6b8fbaa0..cca3c199 100644 --- a/examples/NpgsqlLegacyExample/QuerySql.cs +++ b/examples/NpgsqlLegacyExample/QuerySql.cs @@ -20,6 +20,12 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } + public QuerySql(NpgsqlTransaction transaction) + { + this.Transaction = transaction; + } + + private NpgsqlTransaction Transaction { get; } private string ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; @@ -35,24 +41,53 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorSql)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -67,20 +102,44 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(ListAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(ListAuthorsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -100,26 +159,57 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(CreateAuthorSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(CreateAuthorSql)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - return new CreateAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new CreateAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new CreateAuthorRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -137,16 +227,34 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(CreateAuthorReturnIdSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt64(result); + using (var command = connection.CreateCommand(CreateAuthorReturnIdSql)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorReturnIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -162,24 +270,53 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorByIdSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorByIdSql)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorByIdRow + if (await reader.ReadAsync()) { - Id = reader.GetInt64(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorByIdRow + { + Id = reader.GetInt64(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -198,21 +335,46 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorByNamePatternSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorByNamePatternSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByNamePatternSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -224,25 +386,60 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(DeleteAuthorSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(DeleteAuthorSql)) + { + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); } } private const string TruncateAuthorsSql = "TRUNCATE TABLE authors CASCADE"; public async Task TruncateAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(TruncateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(TruncateAuthorsSql)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncateAuthorsSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -253,14 +450,30 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(UpdateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - return await command.ExecuteNonQueryAsync(); + using (var command = connection.CreateCommand(UpdateAuthorsSql)) + { + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = UpdateAuthorsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id = ANY(@longArr_1::BIGINT[])"; @@ -276,21 +489,46 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByIdsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@longArr_1", args.LongArr1); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByIdsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByIdsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -309,22 +547,48 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByIdsAndNamesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@longArr_1", args.LongArr1); - command.Parameters.AddWithValue("@stringArr_2", args.StringArr2); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByIdsAndNamesSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + command.Parameters.AddWithValue("@stringArr_2", args.StringArr2); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByIdsAndNamesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@longArr_1", args.LongArr1); + command.Parameters.AddWithValue("@stringArr_2", args.StringArr2); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -341,16 +605,34 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(CreateBookSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@author_id", args.AuthorId); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt64(result); + using (var command = connection.CreateCommand(CreateBookSql)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateBookSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt64(result); + } } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors.id = books.author_id ORDER BY authors.name"; @@ -361,20 +643,44 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(ListAllAuthorsBooksSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -387,20 +693,44 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetDuplicateAuthorsSql)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt64(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -419,21 +749,46 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetAuthorsByBookNameSql)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt64(3), Name = reader.GetString(4), AuthorId = reader.GetInt64(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -465,33 +820,71 @@ public class InsertPostgresTypesArgs }; public async Task InsertPostgresTypes(InsertPostgresTypesArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) - { - using (var command = connection.CreateCommand(InsertPostgresTypesSql)) - { - command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_money", args.CMoney ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_time", args.CTime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_timestamp_with_tz", args.CTimestampWithTz ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_character_varying", args.CCharacterVarying ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_bytea", args.CBytea ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text_array", args.CTextArray ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_integer_array", args.CIntegerArray ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + if (this.Transaction == null) + { + using (var connection = NpgsqlDataSource.Create(ConnectionString)) + { + using (var command = connection.CreateCommand(InsertPostgresTypesSql)) + { + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_money", args.CMoney ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_time", args.CTime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp_with_tz", args.CTimestampWithTz ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_character_varying", args.CCharacterVarying ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bytea", args.CBytea ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text_array", args.CTextArray ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer_array", args.CIntegerArray ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertPostgresTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bigint", args.CBigint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_numeric", args.CNumeric ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_decimal", args.CDecimal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_double_precision", args.CDoublePrecision ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_money", args.CMoney ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_time", args.CTime ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_timestamp_with_tz", args.CTimestampWithTz ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_char", args.CChar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_varchar", args.CVarchar ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_character_varying", args.CCharacterVarying ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_bytea", args.CBytea ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text_array", args.CTextArray ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_integer_array", args.CIntegerArray ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -583,42 +976,89 @@ public class GetPostgresTypesRow }; public async Task GetPostgresTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetPostgresTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetPostgresTypesSql)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetPostgresTypesRow + if (await reader.ReadAsync()) { - CBoolean = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), - CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), - CSmallint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2), - CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3), - CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4), - CDecimal = reader.IsDBNull(5) ? (decimal? )null : reader.GetDecimal(5), - CNumeric = reader.IsDBNull(6) ? (decimal? )null : reader.GetDecimal(6), - CReal = reader.IsDBNull(7) ? (float? )null : reader.GetFloat(7), - CDoublePrecision = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), - CMoney = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), - CDate = reader.IsDBNull(10) ? (DateTime? )null : reader.GetDateTime(10), - CTime = reader.IsDBNull(11) ? (TimeSpan? )null : reader.GetFieldValue(11), - CTimestamp = reader.IsDBNull(12) ? (DateTime? )null : reader.GetDateTime(12), - CTimestampWithTz = reader.IsDBNull(13) ? (DateTime? )null : reader.GetDateTime(13), - CChar = reader.IsDBNull(14) ? null : reader.GetString(14), - CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), - CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), - CBytea = reader.IsDBNull(17) ? null : reader.GetFieldValue(17), - CText = reader.IsDBNull(18) ? null : reader.GetString(18), - CJson = reader.IsDBNull(19) ? null : reader.GetString(19), - CTextArray = reader.IsDBNull(20) ? null : reader.GetFieldValue(20), - CIntegerArray = reader.IsDBNull(21) ? null : reader.GetFieldValue(21) - }; + return new GetPostgresTypesRow + { + CBoolean = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), + CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CSmallint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2), + CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4), + CDecimal = reader.IsDBNull(5) ? (decimal? )null : reader.GetDecimal(5), + CNumeric = reader.IsDBNull(6) ? (decimal? )null : reader.GetDecimal(6), + CReal = reader.IsDBNull(7) ? (float? )null : reader.GetFloat(7), + CDoublePrecision = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? (DateTime? )null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? (TimeSpan? )null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? (DateTime? )null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? (DateTime? )null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CBytea = reader.IsDBNull(17) ? null : reader.GetFieldValue(17), + CText = reader.IsDBNull(18) ? null : reader.GetString(18), + CJson = reader.IsDBNull(19) ? null : reader.GetString(19), + CTextArray = reader.IsDBNull(20) ? null : reader.GetFieldValue(20), + CIntegerArray = reader.IsDBNull(21) ? null : reader.GetFieldValue(21) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetPostgresTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetPostgresTypesRow + { + CBoolean = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), + CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CSmallint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2), + CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4), + CDecimal = reader.IsDBNull(5) ? (decimal? )null : reader.GetDecimal(5), + CNumeric = reader.IsDBNull(6) ? (decimal? )null : reader.GetDecimal(6), + CReal = reader.IsDBNull(7) ? (float? )null : reader.GetFloat(7), + CDoublePrecision = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? (DateTime? )null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? (TimeSpan? )null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? (DateTime? )null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? (DateTime? )null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CBytea = reader.IsDBNull(17) ? null : reader.GetFieldValue(17), + CText = reader.IsDBNull(18) ? null : reader.GetString(18), + CJson = reader.IsDBNull(19) ? null : reader.GetString(19), + CTextArray = reader.IsDBNull(20) ? null : reader.GetFieldValue(20), + CIntegerArray = reader.IsDBNull(21) ? null : reader.GetFieldValue(21) + }; + } + } } return null; @@ -649,39 +1089,83 @@ public class GetPostgresTypesAggRow }; public async Task GetPostgresTypesAgg() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetPostgresTypesAggSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetPostgresTypesAggSql)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetPostgresTypesAggRow + if (await reader.ReadAsync()) { - Cnt = reader.GetInt64(0), - CSmallint = reader.IsDBNull(1) ? (short? )null : reader.GetInt16(1), - CBoolean = reader.IsDBNull(2) ? (bool? )null : reader.GetBoolean(2), - CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3), - CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4), - CReal = reader.IsDBNull(5) ? (float? )null : reader.GetFloat(5), - CNumeric = reader.IsDBNull(6) ? (decimal? )null : reader.GetDecimal(6), - CDecimal = reader.IsDBNull(7) ? (decimal? )null : reader.GetDecimal(7), - CDoublePrecision = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), - CMoney = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), - CDate = reader.IsDBNull(10) ? (DateTime? )null : reader.GetDateTime(10), - CTime = reader.IsDBNull(11) ? (TimeSpan? )null : reader.GetFieldValue(11), - CTimestamp = reader.IsDBNull(12) ? (DateTime? )null : reader.GetDateTime(12), - CTimestampWithTz = reader.IsDBNull(13) ? (DateTime? )null : reader.GetDateTime(13), - CChar = reader.IsDBNull(14) ? null : reader.GetString(14), - CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), - CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), - CText = reader.IsDBNull(17) ? null : reader.GetString(17), - CBytea = reader.IsDBNull(18) ? null : reader.GetFieldValue(18) - }; + return new GetPostgresTypesAggRow + { + Cnt = reader.GetInt64(0), + CSmallint = reader.IsDBNull(1) ? (short? )null : reader.GetInt16(1), + CBoolean = reader.IsDBNull(2) ? (bool? )null : reader.GetBoolean(2), + CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4), + CReal = reader.IsDBNull(5) ? (float? )null : reader.GetFloat(5), + CNumeric = reader.IsDBNull(6) ? (decimal? )null : reader.GetDecimal(6), + CDecimal = reader.IsDBNull(7) ? (decimal? )null : reader.GetDecimal(7), + CDoublePrecision = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? (DateTime? )null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? (TimeSpan? )null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? (DateTime? )null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? (DateTime? )null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CText = reader.IsDBNull(17) ? null : reader.GetString(17), + CBytea = reader.IsDBNull(18) ? null : reader.GetFieldValue(18) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetPostgresTypesAggSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetPostgresTypesAggRow + { + Cnt = reader.GetInt64(0), + CSmallint = reader.IsDBNull(1) ? (short? )null : reader.GetInt16(1), + CBoolean = reader.IsDBNull(2) ? (bool? )null : reader.GetBoolean(2), + CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3), + CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4), + CReal = reader.IsDBNull(5) ? (float? )null : reader.GetFloat(5), + CNumeric = reader.IsDBNull(6) ? (decimal? )null : reader.GetDecimal(6), + CDecimal = reader.IsDBNull(7) ? (decimal? )null : reader.GetDecimal(7), + CDoublePrecision = reader.IsDBNull(8) ? (double? )null : reader.GetDouble(8), + CMoney = reader.IsDBNull(9) ? (decimal? )null : reader.GetDecimal(9), + CDate = reader.IsDBNull(10) ? (DateTime? )null : reader.GetDateTime(10), + CTime = reader.IsDBNull(11) ? (TimeSpan? )null : reader.GetFieldValue(11), + CTimestamp = reader.IsDBNull(12) ? (DateTime? )null : reader.GetDateTime(12), + CTimestampWithTz = reader.IsDBNull(13) ? (DateTime? )null : reader.GetDateTime(13), + CChar = reader.IsDBNull(14) ? null : reader.GetString(14), + CVarchar = reader.IsDBNull(15) ? null : reader.GetString(15), + CCharacterVarying = reader.IsDBNull(16) ? null : reader.GetString(16), + CText = reader.IsDBNull(17) ? null : reader.GetString(17), + CBytea = reader.IsDBNull(18) ? null : reader.GetFieldValue(18) + }; + } + } } return null; @@ -700,19 +1184,43 @@ public class InsertPostgresGeoTypesArgs }; public async Task InsertPostgresGeoTypes(InsertPostgresGeoTypesArgs args) { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(InsertPostgresGeoTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - command.Parameters.AddWithValue("@c_point", args.CPoint ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_line", args.CLine ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_lseg", args.CLseg ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_box", args.CBox ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_path", args.CPath ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_polygon", args.CPolygon ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_circle", args.CCircle ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(InsertPostgresGeoTypesSql)) + { + command.Parameters.AddWithValue("@c_point", args.CPoint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_line", args.CLine ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_lseg", args.CLseg ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_box", args.CBox ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_path", args.CPath ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_polygon", args.CPolygon ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_circle", args.CCircle ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertPostgresGeoTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_point", args.CPoint ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_line", args.CLine ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_lseg", args.CLseg ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_box", args.CBox ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_path", args.CPath ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_polygon", args.CPolygon ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_circle", args.CCircle ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -729,27 +1237,59 @@ public class GetPostgresGeoTypesRow }; public async Task GetPostgresGeoTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(GetPostgresGeoTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + using (var command = connection.CreateCommand(GetPostgresGeoTypesSql)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetPostgresGeoTypesRow + if (await reader.ReadAsync()) { - CPoint = reader.IsDBNull(0) ? (NpgsqlPoint? )null : reader.GetFieldValue(0), - CLine = reader.IsDBNull(1) ? (NpgsqlLine? )null : reader.GetFieldValue(1), - CLseg = reader.IsDBNull(2) ? (NpgsqlLSeg? )null : reader.GetFieldValue(2), - CBox = reader.IsDBNull(3) ? (NpgsqlBox? )null : reader.GetFieldValue(3), - CPath = reader.IsDBNull(4) ? (NpgsqlPath? )null : reader.GetFieldValue(4), - CPolygon = reader.IsDBNull(5) ? (NpgsqlPolygon? )null : reader.GetFieldValue(5), - CCircle = reader.IsDBNull(6) ? (NpgsqlCircle? )null : reader.GetFieldValue(6) - }; + return new GetPostgresGeoTypesRow + { + CPoint = reader.IsDBNull(0) ? (NpgsqlPoint? )null : reader.GetFieldValue(0), + CLine = reader.IsDBNull(1) ? (NpgsqlLine? )null : reader.GetFieldValue(1), + CLseg = reader.IsDBNull(2) ? (NpgsqlLSeg? )null : reader.GetFieldValue(2), + CBox = reader.IsDBNull(3) ? (NpgsqlBox? )null : reader.GetFieldValue(3), + CPath = reader.IsDBNull(4) ? (NpgsqlPath? )null : reader.GetFieldValue(4), + CPolygon = reader.IsDBNull(5) ? (NpgsqlPolygon? )null : reader.GetFieldValue(5), + CCircle = reader.IsDBNull(6) ? (NpgsqlCircle? )null : reader.GetFieldValue(6) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetPostgresGeoTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetPostgresGeoTypesRow + { + CPoint = reader.IsDBNull(0) ? (NpgsqlPoint? )null : reader.GetFieldValue(0), + CLine = reader.IsDBNull(1) ? (NpgsqlLine? )null : reader.GetFieldValue(1), + CLseg = reader.IsDBNull(2) ? (NpgsqlLSeg? )null : reader.GetFieldValue(2), + CBox = reader.IsDBNull(3) ? (NpgsqlBox? )null : reader.GetFieldValue(3), + CPath = reader.IsDBNull(4) ? (NpgsqlPath? )null : reader.GetFieldValue(4), + CPolygon = reader.IsDBNull(5) ? (NpgsqlPolygon? )null : reader.GetFieldValue(5), + CCircle = reader.IsDBNull(6) ? (NpgsqlCircle? )null : reader.GetFieldValue(6) + }; + } + } } return null; @@ -758,24 +1298,58 @@ public async Task GetPostgresGeoTypes() private const string TruncatePostgresTypesSql = "TRUNCATE TABLE postgres_types"; public async Task TruncatePostgresTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(TruncatePostgresTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(TruncatePostgresTypesSql)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncatePostgresTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } private const string TruncatePostgresGeoTypesSql = "TRUNCATE TABLE postgres_geometric_types"; public async Task TruncatePostgresGeoTypes() { - using (var connection = NpgsqlDataSource.Create(ConnectionString)) + if (this.Transaction == null) { - using (var command = connection.CreateCommand(TruncatePostgresGeoTypesSql)) + using (var connection = NpgsqlDataSource.Create(ConnectionString)) { - await command.ExecuteScalarAsync(); + using (var command = connection.CreateCommand(TruncatePostgresGeoTypesSql)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = TruncatePostgresGeoTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } } diff --git a/examples/SqliteDapperExample/QuerySql.cs b/examples/SqliteDapperExample/QuerySql.cs index 8acc4c2f..1d5e2ca4 100644 --- a/examples/SqliteDapperExample/QuerySql.cs +++ b/examples/SqliteDapperExample/QuerySql.cs @@ -19,7 +19,14 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - private string ConnectionString { get; } + public QuerySql(SqliteTransaction transaction) + { + this.Transaction = transaction; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; + } + + private SqliteTransaction? Transaction { get; } + private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; public class GetAuthorRow @@ -34,13 +41,23 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams, transaction: this.Transaction); } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name"; @@ -52,11 +69,21 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(ListAuthorsSql); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryAsync(ListAuthorsSql); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(ListAuthorsSql, transaction: this.Transaction)).AsList(); } private const string CreateAuthorSql = "INSERT INTO authors (id, name, bio) VALUES (@id, @name, @bio)"; @@ -68,14 +95,26 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(CreateAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - await connection.ExecuteAsync(CreateAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(CreateAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio) RETURNING id"; @@ -90,13 +129,23 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -112,13 +161,23 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByNamePatternSql = "SELECT id, name, bio FROM authors WHERE name LIKE COALESCE(@name_pattern, '%')"; @@ -134,13 +193,23 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name_pattern", args.NamePattern); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name_pattern", args.NamePattern); - var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorByNamePatternSql, queryParams, transaction: this.Transaction)).AsList(); } private const string UpdateAuthorsSql = "UPDATE authors SET bio = @bio WHERE bio IS NOT NULL "; @@ -150,12 +219,22 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio", args.Bio); - return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.ExecuteAsync(UpdateAuthorsSql, queryParams, transaction: this.Transaction); } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids)"; @@ -171,16 +250,26 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string GetAuthorsByIdsAndNamesSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids) AND name IN (/*SLICE:names*/@names)"; @@ -197,19 +286,29 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + queryParams.Add($"@namesArg{i}", args.Names[i]); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - queryParams.Add($"@namesArg{i}", args.Names[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string DeleteAuthorSql = "DELETE FROM authors WHERE name = @name"; @@ -219,12 +318,24 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateBookSql = "INSERT INTO books (name, author_id) VALUES (@name, @author_id) RETURNING id"; @@ -239,13 +350,23 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("author_id", args.AuthorId); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateBookSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("author_id", args.AuthorId); - return await connection.QuerySingleAsync(CreateBookSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateBookSql, queryParams, transaction: this.Transaction); } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name "; @@ -256,21 +377,45 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -283,21 +428,45 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -316,22 +485,47 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -339,10 +533,22 @@ public async Task> GetAuthorsByBookName(GetAuthors private const string DeleteAllAuthorsSql = "DELETE FROM authors"; public async Task DeleteAllAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAllAuthorsSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(DeleteAllAuthorsSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAllAuthorsSql, transaction: this.Transaction); } private const string InsertSqliteTypesSql = "INSERT INTO types_sqlite (c_integer, c_real, c_text, c_blob) VALUES (@c_integer, @c_real, @c_text, @c_blob)"; @@ -355,15 +561,27 @@ public class InsertSqliteTypesArgs }; public async Task InsertSqliteTypes(InsertSqliteTypesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("c_integer", args.CInteger); + queryParams.Add("c_real", args.CReal); + queryParams.Add("c_text", args.CText); + queryParams.Add("c_blob", args.CBlob); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertSqliteTypesSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("c_integer", args.CInteger); - queryParams.Add("c_real", args.CReal); - queryParams.Add("c_text", args.CText); - queryParams.Add("c_blob", args.CBlob); - await connection.ExecuteAsync(InsertSqliteTypesSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(InsertSqliteTypesSql, queryParams, transaction: this.Transaction); } private const string InsertSqliteTypesBatchSql = "INSERT INTO types_sqlite (c_integer, c_real, c_text) VALUES (@c_integer, @c_real, @c_text)"; @@ -403,11 +621,21 @@ public class GetSqliteTypesRow }; public async Task GetSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetSqliteTypesSql, transaction: this.Transaction); } private const string GetSqliteTypesAggSql = "SELECT COUNT(1) AS cnt , c_integer, c_real, c_text, c_blob FROM types_sqlite GROUP BY c_integer , c_real, c_text, c_blob LIMIT 1 "; @@ -421,19 +649,41 @@ public class GetSqliteTypesAggRow }; public async Task GetSqliteTypesAgg() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesAggSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesAggSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetSqliteTypesAggSql, transaction: this.Transaction); } private const string DeleteAllSqliteTypesSql = "DELETE FROM types_sqlite"; public async Task DeleteAllSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAllSqliteTypesSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(DeleteAllSqliteTypesSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAllSqliteTypesSql, transaction: this.Transaction); } } \ No newline at end of file diff --git a/examples/SqliteDapperLegacyExample/QuerySql.cs b/examples/SqliteDapperLegacyExample/QuerySql.cs index 7a7735b7..127005ec 100644 --- a/examples/SqliteDapperLegacyExample/QuerySql.cs +++ b/examples/SqliteDapperLegacyExample/QuerySql.cs @@ -20,6 +20,13 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } + public QuerySql(SqliteTransaction transaction) + { + this.Transaction = transaction; + Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; + } + + private SqliteTransaction Transaction { get; } private string ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; @@ -35,13 +42,23 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorSql, queryParams, transaction: this.Transaction); } private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name"; @@ -53,11 +70,21 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(ListAuthorsSql); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryAsync(ListAuthorsSql); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(ListAuthorsSql, transaction: this.Transaction)).AsList(); } private const string CreateAuthorSql = "INSERT INTO authors (id, name, bio) VALUES (@id, @name, @bio)"; @@ -69,14 +96,26 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(CreateAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - await connection.ExecuteAsync(CreateAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(CreateAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateAuthorReturnIdSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio) RETURNING id"; @@ -91,13 +130,23 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("bio", args.Bio); - return await connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateAuthorReturnIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -113,13 +162,23 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("id", args.Id); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("id", args.Id); - var result = await connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetAuthorByIdSql, queryParams, transaction: this.Transaction); } private const string GetAuthorByNamePatternSql = "SELECT id, name, bio FROM authors WHERE name LIKE COALESCE(@name_pattern, '%')"; @@ -135,13 +194,23 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name_pattern", args.NamePattern); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name_pattern", args.NamePattern); - var result = await connection.QueryAsync(GetAuthorByNamePatternSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(GetAuthorByNamePatternSql, queryParams, transaction: this.Transaction)).AsList(); } private const string UpdateAuthorsSql = "UPDATE authors SET bio = @bio WHERE bio IS NOT NULL "; @@ -151,12 +220,22 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("bio", args.Bio); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("bio", args.Bio); - return await connection.ExecuteAsync(UpdateAuthorsSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.ExecuteAsync(UpdateAuthorsSql, queryParams, transaction: this.Transaction); } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids)"; @@ -172,16 +251,26 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string GetAuthorsByIdsAndNamesSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids) AND name IN (/*SLICE:names*/@names)"; @@ -198,19 +287,29 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + var queryParams = new Dictionary(); + for (int i = 0; i < args.Ids.Length; i++) + queryParams.Add($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + queryParams.Add($"@namesArg{i}", args.Names[i]); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryAsync(transformedSql, queryParams); + return result.AsList(); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - var queryParams = new Dictionary(); - for (int i = 0; i < args.Ids.Length; i++) - queryParams.Add($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - queryParams.Add($"@namesArg{i}", args.Names[i]); - var result = await connection.QueryAsync(transformedSql, queryParams); - return result.AsList(); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return (await this.Transaction.Connection.QueryAsync(transformedSql, queryParams, transaction: this.Transaction)).AsList(); } private const string DeleteAuthorSql = "DELETE FROM authors WHERE name = @name"; @@ -220,12 +319,24 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - await connection.ExecuteAsync(DeleteAuthorSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAuthorSql, queryParams, transaction: this.Transaction); } private const string CreateBookSql = "INSERT INTO books (name, author_id) VALUES (@name, @author_id) RETURNING id"; @@ -240,13 +351,23 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("name", args.Name); + queryParams.Add("author_id", args.AuthorId); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + return await connection.QuerySingleAsync(CreateBookSql, queryParams); + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("name", args.Name); - queryParams.Add("author_id", args.AuthorId); - return await connection.QuerySingleAsync(CreateBookSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QuerySingleAsync(CreateBookSql, queryParams, transaction: this.Transaction); } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name "; @@ -257,21 +378,45 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -284,21 +429,45 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -317,22 +486,47 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -340,10 +534,22 @@ public async Task> GetAuthorsByBookName(GetAuthors private const string DeleteAllAuthorsSql = "DELETE FROM authors"; public async Task DeleteAllAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAllAuthorsSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(DeleteAllAuthorsSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAllAuthorsSql, transaction: this.Transaction); } private const string InsertSqliteTypesSql = "INSERT INTO types_sqlite (c_integer, c_real, c_text, c_blob) VALUES (@c_integer, @c_real, @c_text, @c_blob)"; @@ -356,15 +562,27 @@ public class InsertSqliteTypesArgs }; public async Task InsertSqliteTypes(InsertSqliteTypesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var queryParams = new Dictionary(); + queryParams.Add("c_integer", args.CInteger); + queryParams.Add("c_real", args.CReal); + queryParams.Add("c_text", args.CText); + queryParams.Add("c_blob", args.CBlob); + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(InsertSqliteTypesSql, queryParams); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var queryParams = new Dictionary(); - queryParams.Add("c_integer", args.CInteger); - queryParams.Add("c_real", args.CReal); - queryParams.Add("c_text", args.CText); - queryParams.Add("c_blob", args.CBlob); - await connection.ExecuteAsync(InsertSqliteTypesSql, queryParams); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(InsertSqliteTypesSql, queryParams, transaction: this.Transaction); } private const string InsertSqliteTypesBatchSql = "INSERT INTO types_sqlite (c_integer, c_real, c_text) VALUES (@c_integer, @c_real, @c_text)"; @@ -404,11 +622,21 @@ public class GetSqliteTypesRow }; public async Task GetSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetSqliteTypesSql, transaction: this.Transaction); } private const string GetSqliteTypesAggSql = "SELECT COUNT(1) AS cnt , c_integer, c_real, c_text, c_blob FROM types_sqlite GROUP BY c_integer , c_real, c_text, c_blob LIMIT 1 "; @@ -422,20 +650,42 @@ public class GetSqliteTypesAggRow }; public async Task GetSqliteTypesAgg() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesAggSql); + return result; + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - var result = await connection.QueryFirstOrDefaultAsync(GetSqliteTypesAggSql); - return result; + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + return await this.Transaction.Connection.QueryFirstOrDefaultAsync(GetSqliteTypesAggSql, transaction: this.Transaction); } private const string DeleteAllSqliteTypesSql = "DELETE FROM types_sqlite"; public async Task DeleteAllSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) + { + using (var connection = new SqliteConnection(ConnectionString)) + { + await connection.ExecuteAsync(DeleteAllSqliteTypesSql); + } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) { - await connection.ExecuteAsync(DeleteAllSqliteTypesSql); + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); } + + await this.Transaction.Connection.ExecuteAsync(DeleteAllSqliteTypesSql, transaction: this.Transaction); } } } \ No newline at end of file diff --git a/examples/SqliteExample/QuerySql.cs b/examples/SqliteExample/QuerySql.cs index e8201b25..dc9a7d83 100644 --- a/examples/SqliteExample/QuerySql.cs +++ b/examples/SqliteExample/QuerySql.cs @@ -17,32 +17,67 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - private string ConnectionString { get; } + public QuerySql(SqliteTransaction transaction) + { + this.Transaction = transaction; + } + + private SqliteTransaction? Transaction { get; } + private string? ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; public readonly record struct GetAuthorRow(int Id, string Name, string? Bio); public readonly record struct GetAuthorArgs(string Name); public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt32(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -52,21 +87,45 @@ public QuerySql(string connectionString) public readonly record struct ListAuthorsRow(int Id, string Name, string? Bio); public async Task> ListAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(ListAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(ListAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAuthorsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -75,16 +134,36 @@ public async Task> ListAuthors() public readonly record struct CreateAuthorArgs(int Id, string Name, string? Bio); public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(CreateAuthorSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(CreateAuthorSql, connection)) + { + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -93,17 +172,35 @@ public async Task CreateAuthor(CreateAuthorArgs args) public readonly record struct CreateAuthorReturnIdArgs(string Name, string? Bio); public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(CreateAuthorReturnIdSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt32(result); + await connection.OpenAsync(); + using (var command = new SqliteCommand(CreateAuthorReturnIdSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorReturnIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -111,25 +208,54 @@ public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) public readonly record struct GetAuthorByIdArgs(int Id); public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorByIdSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorByIdSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorByIdRow + if (await reader.ReadAsync()) { - Id = reader.GetInt32(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorByIdRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorByIdRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -140,22 +266,47 @@ public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) public readonly record struct GetAuthorByNamePatternArgs(string? NamePattern); public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorByNamePatternSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorByNamePatternSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByNamePatternSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -164,15 +315,31 @@ public async Task> GetAuthorByNamePattern(GetAut public readonly record struct UpdateAuthorsArgs(string? Bio); public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(UpdateAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - return await command.ExecuteNonQueryAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(UpdateAuthorsSql, connection)) + { + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = UpdateAuthorsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids)"; @@ -180,25 +347,51 @@ public async Task UpdateAuthors(UpdateAuthorsArgs args) public readonly record struct GetAuthorsByIdsArgs(int[] Ids); public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - using (var command = new SqliteCommand(transformedSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(transformedSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -208,28 +401,56 @@ public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs public readonly record struct GetAuthorsByIdsAndNamesArgs(int[] Ids, string[] Names); public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - using (var command = new SqliteCommand(transformedSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(transformedSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -238,14 +459,32 @@ public async Task> GetAuthorsByIdsAndNames(GetA public readonly record struct DeleteAuthorArgs(string Name); public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(DeleteAuthorSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(DeleteAuthorSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); } } @@ -254,38 +493,80 @@ public async Task DeleteAuthor(DeleteAuthorArgs args) public readonly record struct CreateBookArgs(string Name, int AuthorId); public async Task CreateBook(CreateBookArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(CreateBookSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@author_id", args.AuthorId); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt32(result); + await connection.OpenAsync(); + using (var command = new SqliteCommand(CreateBookSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateBookSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name "; public readonly record struct ListAllAuthorsBooksRow(Author? Author, Book? Book); public async Task> ListAllAuthorsBooks() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -294,21 +575,45 @@ public async Task> ListAllAuthorsBooks() public readonly record struct GetDuplicateAuthorsRow(Author? Author, Author? Author2); public async Task> GetDuplicateAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -318,22 +623,47 @@ public async Task> GetDuplicateAuthors() public readonly record struct GetAuthorsByBookNameArgs(string Name); public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -341,13 +671,30 @@ public async Task> GetAuthorsByBookName(GetAuthors private const string DeleteAllAuthorsSql = "DELETE FROM authors"; public async Task DeleteAllAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(DeleteAllAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(DeleteAllAuthorsSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAllAuthorsSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -355,17 +702,38 @@ public async Task DeleteAllAuthors() public readonly record struct InsertSqliteTypesArgs(int? CInteger, decimal? CReal, string? CText, byte[]? CBlob); public async Task InsertSqliteTypes(InsertSqliteTypesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(InsertSqliteTypesSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(InsertSqliteTypesSql, connection)) + { + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertSqliteTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -395,25 +763,54 @@ public async Task InsertSqliteTypesBatch(List args) public readonly record struct GetSqliteTypesRow(int? CInteger, decimal? CReal, string? CText, byte[]? CBlob); public async Task GetSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetSqliteTypesSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetSqliteTypesSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetSqliteTypesRow + if (await reader.ReadAsync()) { - CInteger = reader.IsDBNull(0) ? null : reader.GetInt32(0), - CReal = reader.IsDBNull(1) ? null : reader.GetDecimal(1), - CText = reader.IsDBNull(2) ? null : reader.GetString(2), - CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue(3) - }; + return new GetSqliteTypesRow + { + CInteger = reader.IsDBNull(0) ? null : reader.GetInt32(0), + CReal = reader.IsDBNull(1) ? null : reader.GetDecimal(1), + CText = reader.IsDBNull(2) ? null : reader.GetString(2), + CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue(3) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetSqliteTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetSqliteTypesRow + { + CInteger = reader.IsDBNull(0) ? null : reader.GetInt32(0), + CReal = reader.IsDBNull(1) ? null : reader.GetDecimal(1), + CText = reader.IsDBNull(2) ? null : reader.GetString(2), + CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue(3) + }; + } + } } return null; @@ -423,26 +820,56 @@ public async Task InsertSqliteTypesBatch(List args) public readonly record struct GetSqliteTypesAggRow(int Cnt, int? CInteger, decimal? CReal, string? CText, byte[]? CBlob); public async Task GetSqliteTypesAgg() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetSqliteTypesAggSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetSqliteTypesAggSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetSqliteTypesAggRow + if (await reader.ReadAsync()) { - Cnt = reader.GetInt32(0), - CInteger = reader.IsDBNull(1) ? null : reader.GetInt32(1), - CReal = reader.IsDBNull(2) ? null : reader.GetDecimal(2), - CText = reader.IsDBNull(3) ? null : reader.GetString(3), - CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue(4) - }; + return new GetSqliteTypesAggRow + { + Cnt = reader.GetInt32(0), + CInteger = reader.IsDBNull(1) ? null : reader.GetInt32(1), + CReal = reader.IsDBNull(2) ? null : reader.GetDecimal(2), + CText = reader.IsDBNull(3) ? null : reader.GetString(3), + CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue(4) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetSqliteTypesAggSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetSqliteTypesAggRow + { + Cnt = reader.GetInt32(0), + CInteger = reader.IsDBNull(1) ? null : reader.GetInt32(1), + CReal = reader.IsDBNull(2) ? null : reader.GetDecimal(2), + CText = reader.IsDBNull(3) ? null : reader.GetString(3), + CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue(4) + }; + } + } } return null; @@ -451,13 +878,30 @@ public async Task InsertSqliteTypesBatch(List args) private const string DeleteAllSqliteTypesSql = "DELETE FROM types_sqlite"; public async Task DeleteAllSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(DeleteAllSqliteTypesSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(DeleteAllSqliteTypesSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAllSqliteTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } } \ No newline at end of file diff --git a/examples/SqliteLegacyExample/QuerySql.cs b/examples/SqliteLegacyExample/QuerySql.cs index 64ed75db..e3ac61e2 100644 --- a/examples/SqliteLegacyExample/QuerySql.cs +++ b/examples/SqliteLegacyExample/QuerySql.cs @@ -18,6 +18,12 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } + public QuerySql(SqliteTransaction transaction) + { + this.Transaction = transaction; + } + + private SqliteTransaction Transaction { get; } private string ConnectionString { get; } private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1"; @@ -33,25 +39,54 @@ public class GetAuthorArgs }; public async Task GetAuthor(GetAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorRow + if (await reader.ReadAsync()) { - Id = reader.GetInt32(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -66,21 +101,45 @@ public class ListAuthorsRow }; public async Task> ListAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(ListAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(ListAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAuthorsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAuthorsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -94,16 +153,36 @@ public class CreateAuthorArgs }; public async Task CreateAuthor(CreateAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(CreateAuthorSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(CreateAuthorSql, connection)) + { + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -119,17 +198,35 @@ public class CreateAuthorReturnIdArgs }; public async Task CreateAuthorReturnId(CreateAuthorReturnIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(CreateAuthorReturnIdSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt32(result); + await connection.OpenAsync(); + using (var command = new SqliteCommand(CreateAuthorReturnIdSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateAuthorReturnIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } private const string GetAuthorByIdSql = "SELECT id, name, bio FROM authors WHERE id = @id LIMIT 1"; @@ -145,25 +242,54 @@ public class GetAuthorByIdArgs }; public async Task GetAuthorById(GetAuthorByIdArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorByIdSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@id", args.Id); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorByIdSql, connection)) { - if (await reader.ReadAsync()) + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) { - return new GetAuthorByIdRow + if (await reader.ReadAsync()) { - Id = reader.GetInt32(0), - Name = reader.GetString(1), - Bio = reader.IsDBNull(2) ? null : reader.GetString(2) - }; + return new GetAuthorByIdRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByIdSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@id", args.Id); + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetAuthorByIdRow + { + Id = reader.GetInt32(0), + Name = reader.GetString(1), + Bio = reader.IsDBNull(2) ? null : reader.GetString(2) + }; + } + } } return null; @@ -182,22 +308,47 @@ public class GetAuthorByNamePatternArgs }; public async Task> GetAuthorByNamePattern(GetAuthorByNamePatternArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorByNamePatternSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorByNamePatternSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorByNamePatternSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name_pattern", args.NamePattern ?? (object)DBNull.Value); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorByNamePatternRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -209,15 +360,31 @@ public class UpdateAuthorsArgs }; public async Task UpdateAuthors(UpdateAuthorsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(UpdateAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); - return await command.ExecuteNonQueryAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(UpdateAuthorsSql, connection)) + { + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = UpdateAuthorsSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@bio", args.Bio ?? (object)DBNull.Value); + return await command.ExecuteNonQueryAsync(); + } } private const string GetAuthorsByIdsSql = "SELECT id, name, bio FROM authors WHERE id IN (/*SLICE:ids*/@ids)"; @@ -233,25 +400,51 @@ public class GetAuthorsByIdsArgs }; public async Task> GetAuthorsByIds(GetAuthorsByIdsArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - using (var command = new SqliteCommand(transformedSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(transformedSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -270,28 +463,56 @@ public class GetAuthorsByIdsAndNamesArgs }; public async Task> GetAuthorsByIdsAndNames(GetAuthorsByIdsAndNamesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + var transformedSql = GetAuthorsByIdsAndNamesSql; + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); + transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); + if (this.Transaction == null) { - await connection.OpenAsync(); - var transformedSql = GetAuthorsByIdsAndNamesSql; - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Ids.Length, "ids"); - transformedSql = Utils.TransformQueryForSliceArgs(transformedSql, args.Names.Length, "names"); - using (var command = new SqliteCommand(transformedSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - for (int i = 0; i < args.Ids.Length; i++) - command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); - for (int i = 0; i < args.Names.Length; i++) - command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(transformedSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = transformedSql; + command.Transaction = this.Transaction; + for (int i = 0; i < args.Ids.Length; i++) + command.Parameters.AddWithValue($"@idsArg{i}", args.Ids[i]); + for (int i = 0; i < args.Names.Length; i++) + command.Parameters.AddWithValue($"@namesArg{i}", args.Names[i]); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByIdsAndNamesRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }); } + + return result; } } } @@ -303,14 +524,32 @@ public class DeleteAuthorArgs }; public async Task DeleteAuthor(DeleteAuthorArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(DeleteAuthorSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(DeleteAuthorSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAuthorSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + await command.ExecuteNonQueryAsync(); } } @@ -326,17 +565,35 @@ public class CreateBookArgs }; public async Task CreateBook(CreateBookArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(CreateBookSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - command.Parameters.AddWithValue("@author_id", args.AuthorId); - var result = await command.ExecuteScalarAsync(); - return Convert.ToInt32(result); + await connection.OpenAsync(); + using (var command = new SqliteCommand(CreateBookSql, connection)) + { + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = CreateBookSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + command.Parameters.AddWithValue("@author_id", args.AuthorId); + var result = await command.ExecuteScalarAsync(); + return Convert.ToInt32(result); + } } private const string ListAllAuthorsBooksSql = "SELECT authors.id, authors.name, authors.bio, books.id, books.name, books.author_id, books.description FROM authors JOIN books ON authors . id = books . author_id ORDER BY authors . name "; @@ -347,21 +604,45 @@ public class ListAllAuthorsBooksRow }; public async Task> ListAllAuthorsBooks() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(ListAllAuthorsBooksSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } - return result; + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = ListAllAuthorsBooksSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new ListAllAuthorsBooksRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -374,21 +655,45 @@ public class GetDuplicateAuthorsRow }; public async Task> GetDuplicateAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetDuplicateAuthorsSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetDuplicateAuthorsSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetDuplicateAuthorsRow { Author = new Author { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) }, Author2 = new Author { Id = reader.GetInt32(3), Name = reader.GetString(4), Bio = reader.IsDBNull(5) ? null : reader.GetString(5) } }); } + + return result; } } } @@ -407,22 +712,47 @@ public class GetAuthorsByBookNameArgs }; public async Task> GetAuthorsByBookName(GetAuthorsByBookNameArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@name", args.Name); - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetAuthorsByBookNameSql, connection)) { - var result = new List(); - while (await reader.ReadAsync()) + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) { - result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); + } + + return result; } + } + } + } - return result; + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetAuthorsByBookNameSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@name", args.Name); + using (var reader = await command.ExecuteReaderAsync()) + { + var result = new List(); + while (await reader.ReadAsync()) + { + result.Add(new GetAuthorsByBookNameRow { Id = reader.GetInt32(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Book = new Book { Id = reader.GetInt32(3), Name = reader.GetString(4), AuthorId = reader.GetInt32(5), Description = reader.IsDBNull(6) ? null : reader.GetString(6) } }); } + + return result; } } } @@ -430,13 +760,30 @@ public async Task> GetAuthorsByBookName(GetAuthors private const string DeleteAllAuthorsSql = "DELETE FROM authors"; public async Task DeleteAllAuthors() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(DeleteAllAuthorsSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(DeleteAllAuthorsSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAllAuthorsSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } @@ -450,17 +797,38 @@ public class InsertSqliteTypesArgs }; public async Task InsertSqliteTypes(InsertSqliteTypesArgs args) { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(InsertSqliteTypesSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(InsertSqliteTypesSql, connection)) + { + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = InsertSqliteTypesSql; + command.Transaction = this.Transaction; + command.Parameters.AddWithValue("@c_integer", args.CInteger ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_real", args.CReal ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@c_blob", args.CBlob ?? (object)DBNull.Value); + await command.ExecuteNonQueryAsync(); } } @@ -501,25 +869,54 @@ public class GetSqliteTypesRow }; public async Task GetSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetSqliteTypesSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetSqliteTypesSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetSqliteTypesRow + if (await reader.ReadAsync()) { - CInteger = reader.IsDBNull(0) ? (int? )null : reader.GetInt32(0), - CReal = reader.IsDBNull(1) ? (decimal? )null : reader.GetDecimal(1), - CText = reader.IsDBNull(2) ? null : reader.GetString(2), - CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue(3) - }; + return new GetSqliteTypesRow + { + CInteger = reader.IsDBNull(0) ? (int? )null : reader.GetInt32(0), + CReal = reader.IsDBNull(1) ? (decimal? )null : reader.GetDecimal(1), + CText = reader.IsDBNull(2) ? null : reader.GetString(2), + CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue(3) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetSqliteTypesSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetSqliteTypesRow + { + CInteger = reader.IsDBNull(0) ? (int? )null : reader.GetInt32(0), + CReal = reader.IsDBNull(1) ? (decimal? )null : reader.GetDecimal(1), + CText = reader.IsDBNull(2) ? null : reader.GetString(2), + CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue(3) + }; + } + } } return null; @@ -536,26 +933,56 @@ public class GetSqliteTypesAggRow }; public async Task GetSqliteTypesAgg() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(GetSqliteTypesAggSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - using (var reader = await command.ExecuteReaderAsync()) + await connection.OpenAsync(); + using (var command = new SqliteCommand(GetSqliteTypesAggSql, connection)) { - if (await reader.ReadAsync()) + using (var reader = await command.ExecuteReaderAsync()) { - return new GetSqliteTypesAggRow + if (await reader.ReadAsync()) { - Cnt = reader.GetInt32(0), - CInteger = reader.IsDBNull(1) ? (int? )null : reader.GetInt32(1), - CReal = reader.IsDBNull(2) ? (decimal? )null : reader.GetDecimal(2), - CText = reader.IsDBNull(3) ? null : reader.GetString(3), - CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue(4) - }; + return new GetSqliteTypesAggRow + { + Cnt = reader.GetInt32(0), + CInteger = reader.IsDBNull(1) ? (int? )null : reader.GetInt32(1), + CReal = reader.IsDBNull(2) ? (decimal? )null : reader.GetDecimal(2), + CText = reader.IsDBNull(3) ? null : reader.GetString(3), + CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue(4) + }; + } } } } + + return null; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = GetSqliteTypesAggSql; + command.Transaction = this.Transaction; + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + return new GetSqliteTypesAggRow + { + Cnt = reader.GetInt32(0), + CInteger = reader.IsDBNull(1) ? (int? )null : reader.GetInt32(1), + CReal = reader.IsDBNull(2) ? (decimal? )null : reader.GetDecimal(2), + CText = reader.IsDBNull(3) ? null : reader.GetString(3), + CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue(4) + }; + } + } } return null; @@ -564,13 +991,30 @@ public async Task GetSqliteTypesAgg() private const string DeleteAllSqliteTypesSql = "DELETE FROM types_sqlite"; public async Task DeleteAllSqliteTypes() { - using (var connection = new SqliteConnection(ConnectionString)) + if (this.Transaction == null) { - await connection.OpenAsync(); - using (var command = new SqliteCommand(DeleteAllSqliteTypesSql, connection)) + using (var connection = new SqliteConnection(ConnectionString)) { - await command.ExecuteScalarAsync(); + await connection.OpenAsync(); + using (var command = new SqliteCommand(DeleteAllSqliteTypesSql, connection)) + { + await command.ExecuteNonQueryAsync(); + } } + + return; + } + + if (this.Transaction?.Connection == null || this.Transaction?.Connection.State != System.Data.ConnectionState.Open) + { + throw new System.InvalidOperationException("Transaction is provided, but its connection is null."); + } + + using (var command = this.Transaction.Connection.CreateCommand()) + { + command.CommandText = DeleteAllSqliteTypesSql; + command.Transaction = this.Transaction; + await command.ExecuteNonQueryAsync(); } } } From 5408f9bdf0863cee44c4e741df9a8175d7935f35 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 20:19:08 +0300 Subject: [PATCH 03/11] add test for mysql --- end2end/EndToEndScaffold/Config.cs | 3 ++ .../EndToEndScaffold/Templates/MySqlTests.cs | 33 +++++++++++++++++++ .../MySqlConnectorDapperTester.generated.cs | 25 ++++++++++++++ .../MySqlConnectorTester.generated.cs | 25 ++++++++++++++ .../MySqlConnectorDapperTester.generated.cs | 25 ++++++++++++++ .../MySqlConnectorTester.generated.cs | 25 ++++++++++++++ 6 files changed, 136 insertions(+) diff --git a/end2end/EndToEndScaffold/Config.cs b/end2end/EndToEndScaffold/Config.cs index b47cf491..7418f695 100644 --- a/end2end/EndToEndScaffold/Config.cs +++ b/end2end/EndToEndScaffold/Config.cs @@ -50,6 +50,7 @@ public enum KnownTestType // MySql MySqlStringDataTypes, MySqlIntegerDataTypes, + MySqlTransaction, MySqlFloatingPointDataTypes, MySqlDateTimeDataTypes, MySqlBinaryDataTypes, @@ -89,6 +90,7 @@ internal static class Config KnownTestType.MySqlStringDataTypes, KnownTestType.MySqlIntegerDataTypes, + KnownTestType.MySqlTransaction, KnownTestType.MySqlFloatingPointDataTypes, KnownTestType.MySqlDateTimeDataTypes, KnownTestType.MySqlBinaryDataTypes, @@ -124,6 +126,7 @@ internal static class Config KnownTestType.MySqlStringDataTypes, KnownTestType.MySqlIntegerDataTypes, + KnownTestType.MySqlTransaction, KnownTestType.MySqlFloatingPointDataTypes, KnownTestType.MySqlDateTimeDataTypes, KnownTestType.MySqlBinaryDataTypes, diff --git a/end2end/EndToEndScaffold/Templates/MySqlTests.cs b/end2end/EndToEndScaffold/Templates/MySqlTests.cs index 06d1ea2e..5e602b5a 100644 --- a/end2end/EndToEndScaffold/Templates/MySqlTests.cs +++ b/end2end/EndToEndScaffold/Templates/MySqlTests.cs @@ -523,6 +523,39 @@ public async Task TestBinaryCopyFrom( } """ }, + [KnownTestType.MySqlTransaction] = new TestImpl + { + Impl = $$""" + [Test] + public async Task TestMySqlTransaction() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) + // if it were a non-nullable struct/record, actualNull == null would always be false. + // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. + // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + + await transaction.CommitAsync(); + + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}})); // Apply placeholder here + } + """ + }, [KnownTestType.MySqlEnumCopyFrom] = new TestImpl { Impl = $$""" diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index a9de91c1..14cc4b5b 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -361,6 +361,31 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin Assert.That(actual.CBigint, Is.EqualTo(expected.CBigint)); } + [Test] + public async Task TestMySqlTransaction() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) + // if it were a non-nullable struct/record, actualNull == null would always be false. + // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. + // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs index c943a2ff..9dff56ce 100644 --- a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs @@ -361,6 +361,31 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin Assert.That(actual.Value.CBigint, Is.EqualTo(expected.CBigint)); } + [Test] + public async Task TestMySqlTransaction() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) + // if it were a non-nullable struct/record, actualNull == null would always be false. + // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. + // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs index 2af4e2f8..b668da79 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs @@ -361,6 +361,31 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin Assert.That(actual.CBigint, Is.EqualTo(expected.CBigint)); } + [Test] + public async Task TestMySqlTransaction() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) + // if it were a non-nullable struct/record, actualNull == null would always be false. + // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. + // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs index eeb3b2a2..01e6c7ef 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs @@ -361,6 +361,31 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin Assert.That(actual.CBigint, Is.EqualTo(expected.CBigint)); } + [Test] + public async Task TestMySqlTransaction() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) + // if it were a non-nullable struct/record, actualNull == null would always be false. + // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. + // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] From 6d66fe43b5e9191f38b0a883f99fe95275ccd800 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 20:39:36 +0300 Subject: [PATCH 04/11] tests --- end2end/EndToEndScaffold/Templates/MySqlTests.cs | 6 +----- .../EndToEndTests/MySqlConnectorDapperTester.generated.cs | 6 +----- end2end/EndToEndTests/MySqlConnectorTester.generated.cs | 6 +----- .../MySqlConnectorDapperTester.generated.cs | 6 +----- .../EndToEndTestsLegacy/MySqlConnectorTester.generated.cs | 6 +----- 5 files changed, 5 insertions(+), 25 deletions(-) diff --git a/end2end/EndToEndScaffold/Templates/MySqlTests.cs b/end2end/EndToEndScaffold/Templates/MySqlTests.cs index 5e602b5a..12a3610a 100644 --- a/end2end/EndToEndScaffold/Templates/MySqlTests.cs +++ b/end2end/EndToEndScaffold/Templates/MySqlTests.cs @@ -529,17 +529,13 @@ public async Task TestBinaryCopyFrom( [Test] public async Task TestMySqlTransaction() { - var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); var sqlQueryWithTx = new QuerySql(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) - // if it were a non-nullable struct/record, actualNull == null would always be false. - // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. - // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index 14cc4b5b..a2088f1b 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -364,15 +364,11 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin [Test] public async Task TestMySqlTransaction() { - var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); var sqlQueryWithTx = new QuerySql(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) - // if it were a non-nullable struct/record, actualNull == null would always be false. - // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. - // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); diff --git a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs index 9dff56ce..c89ff469 100644 --- a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs @@ -364,15 +364,11 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin [Test] public async Task TestMySqlTransaction() { - var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); var sqlQueryWithTx = new QuerySql(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) - // if it were a non-nullable struct/record, actualNull == null would always be false. - // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. - // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs index b668da79..58a35bef 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs @@ -364,15 +364,11 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin [Test] public async Task TestMySqlTransaction() { - var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); var sqlQueryWithTx = new QuerySql(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) - // if it were a non-nullable struct/record, actualNull == null would always be false. - // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. - // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs index 01e6c7ef..ec1cd012 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs @@ -364,15 +364,11 @@ public async Task TestMySqlIntegerTypes(bool? cBool, bool? cBoolean, short? cTin [Test] public async Task TestMySqlTransaction() { - var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)!); + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); var sqlQueryWithTx = new QuerySql(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - // The GetAuthor method in MySqlConnectorExampleGen (non-Dapper) returns QuerySql.GetAuthorRow (non-nullable struct/record) - // if it were a non-nullable struct/record, actualNull == null would always be false. - // However, MySqlConnectorTester.generated.cs uses actual.Value, implying it's nullable. - // Let's assume QuerySql.GetAuthor returns QuerySql.GetAuthorRow? (nullable record struct) for MySqlConnectorExampleGen. var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); From a2d76d5de04f490ff47483b9721273ad5f2286ef Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 20:56:48 +0300 Subject: [PATCH 05/11] add tests --- end2end/EndToEndScaffold/Config.cs | 6 ++++ .../Templates/PostgresTests.cs | 30 +++++++++++++++++++ .../EndToEndScaffold/Templates/SqliteTests.cs | 30 +++++++++++++++++++ .../NpgsqlDapperTester.generated.cs | 22 ++++++++++++++ .../EndToEndTests/NpgsqlTester.generated.cs | 22 ++++++++++++++ .../SqliteDapperTester.generated.cs | 22 ++++++++++++++ .../EndToEndTests/SqliteTester.generated.cs | 22 ++++++++++++++ .../NpgsqlDapperTester.generated.cs | 22 ++++++++++++++ .../NpgsqlTester.generated.cs | 22 ++++++++++++++ .../SqliteDapperTester.generated.cs | 22 ++++++++++++++ .../SqliteTester.generated.cs | 22 ++++++++++++++ 11 files changed, 242 insertions(+) diff --git a/end2end/EndToEndScaffold/Config.cs b/end2end/EndToEndScaffold/Config.cs index 7418f695..2eb7d4ec 100644 --- a/end2end/EndToEndScaffold/Config.cs +++ b/end2end/EndToEndScaffold/Config.cs @@ -29,6 +29,7 @@ public enum KnownTestType // Sqlite SqliteDataTypes, SqliteCopyFrom, + SqliteTransaction, // Postgres PostgresStringDataTypes, @@ -38,6 +39,7 @@ public enum KnownTestType PostgresArrayDataTypes, PostgresStringCopyFrom, + PostgresTransaction, PostgresIntegerCopyFrom, PostgresFloatingPointCopyFrom, PostgresDateTimeCopyFrom, @@ -160,6 +162,7 @@ internal static class Config KnownTestType.NargNull, KnownTestType.NargNotNull, + KnownTestType.PostgresTransaction, KnownTestType.PostgresStringDataTypes, KnownTestType.PostgresIntegerDataTypes, KnownTestType.PostgresFloatingPointDataTypes, @@ -192,6 +195,7 @@ internal static class Config KnownTestType.MultipleArraysAsParams, KnownTestType.NargNull, KnownTestType.NargNotNull, + KnownTestType.PostgresTransaction, KnownTestType.PostgresStringDataTypes, KnownTestType.PostgresIntegerDataTypes, @@ -225,6 +229,7 @@ internal static class Config KnownTestType.MultipleSlices, KnownTestType.NargNull, KnownTestType.NargNotNull, + KnownTestType.SqliteTransaction, KnownTestType.SqliteDataTypes, KnownTestType.SqliteCopyFrom ] @@ -247,6 +252,7 @@ internal static class Config KnownTestType.MultipleSlices, KnownTestType.NargNull, KnownTestType.NargNotNull, + KnownTestType.SqliteTransaction, KnownTestType.SqliteDataTypes, KnownTestType.SqliteCopyFrom ] diff --git a/end2end/EndToEndScaffold/Templates/PostgresTests.cs b/end2end/EndToEndScaffold/Templates/PostgresTests.cs index fd756d22..25e036f6 100644 --- a/end2end/EndToEndScaffold/Templates/PostgresTests.cs +++ b/end2end/EndToEndScaffold/Templates/PostgresTests.cs @@ -484,6 +484,36 @@ public async Task TestPostgresGeoTypes(NpgsqlPoint? cPoint, NpgsqlLine? cLine, N } """ }, + [KnownTestType.PostgresTransaction] = new TestImpl + { + Impl = $$""" + [Test] + public async Task TestPostgresTransaction() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + + await transaction.CommitAsync(); + + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}})); // Apply placeholder here + } + """ + }, }; } \ No newline at end of file diff --git a/end2end/EndToEndScaffold/Templates/SqliteTests.cs b/end2end/EndToEndScaffold/Templates/SqliteTests.cs index 00844445..d1c7f075 100644 --- a/end2end/EndToEndScaffold/Templates/SqliteTests.cs +++ b/end2end/EndToEndScaffold/Templates/SqliteTests.cs @@ -89,5 +89,35 @@ private static void AssertSingularEquals(QuerySql.GetSqliteTypesAggRow expected, } """ }, + [KnownTestType.SqliteTransaction] = new TestImpl + { + Impl = $$""" + [Test] + public async Task TestSqliteTransaction() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + + await transaction.CommitAsync(); + + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}})); // Apply placeholder here + } + """ + }, }; } \ No newline at end of file diff --git a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs index cdbdddb5..f7e35946 100644 --- a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs @@ -412,6 +412,28 @@ public async Task TestStringCopyFrom(int batchSize, string cChar, string cVarcha Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + [Test] + public async Task TestPostgresTransaction() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTests/NpgsqlTester.generated.cs b/end2end/EndToEndTests/NpgsqlTester.generated.cs index 69b41877..d0f2e41c 100644 --- a/end2end/EndToEndTests/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlTester.generated.cs @@ -412,6 +412,28 @@ public async Task TestStringCopyFrom(int batchSize, string cChar, string cVarcha Assert.That(actual.Value.CText, Is.EqualTo(expected.CText)); } + [Test] + public async Task TestPostgresTransaction() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTests/SqliteDapperTester.generated.cs b/end2end/EndToEndTests/SqliteDapperTester.generated.cs index 4763c177..e43f6145 100644 --- a/end2end/EndToEndTests/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTests/SqliteDapperTester.generated.cs @@ -357,5 +357,27 @@ private static void AssertSingularEquals(QuerySql.GetSqliteTypesAggRow expected, Assert.That(actual.CReal, Is.EqualTo(expected.CReal)); Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + + [Test] + public async Task TestSqliteTransaction() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } } } diff --git a/end2end/EndToEndTests/SqliteTester.generated.cs b/end2end/EndToEndTests/SqliteTester.generated.cs index 2695a577..85b7ea2f 100644 --- a/end2end/EndToEndTests/SqliteTester.generated.cs +++ b/end2end/EndToEndTests/SqliteTester.generated.cs @@ -357,5 +357,27 @@ private static void AssertSingularEquals(QuerySql.GetSqliteTypesAggRow expected, Assert.That(actual.CReal, Is.EqualTo(expected.CReal)); Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + + [Test] + public async Task TestSqliteTransaction() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here + } } } diff --git a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs index ed636326..0d3e37a9 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs @@ -412,6 +412,28 @@ public async Task TestStringCopyFrom(int batchSize, string cChar, string cVarcha Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + [Test] + public async Task TestPostgresTransaction() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs index 1c43f210..974f4e73 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs @@ -412,6 +412,28 @@ public async Task TestStringCopyFrom(int batchSize, string cChar, string cVarcha Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + [Test] + public async Task TestPostgresTransaction() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs index 81545761..24b679c6 100644 --- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs @@ -357,5 +357,27 @@ private static void AssertSingularEquals(QuerySql.GetSqliteTypesAggRow expected, Assert.That(actual.CReal, Is.EqualTo(expected.CReal)); Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + + [Test] + public async Task TestSqliteTransaction() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } } } diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs index 9e1b7cc1..a4d4876d 100644 --- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs @@ -357,5 +357,27 @@ private static void AssertSingularEquals(QuerySql.GetSqliteTypesAggRow expected, Assert.That(actual.CReal, Is.EqualTo(expected.CReal)); Assert.That(actual.CText, Is.EqualTo(expected.CText)); } + + [Test] + public async Task TestSqliteTransaction() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = new QuerySql(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) + var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actualNull == null, "there is author"); // This is correct for nullable types + await transaction.CommitAsync(); + var expected = new QuerySql.GetAuthorRow + { + Id = 1111, + Name = "Bojack Horseman", + Bio = "Back in the 90s he was in a very famous TV show" + }; + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(SingularEquals(expected, actual)); // Apply placeholder here + } } } From 09de0177cb1b765abbd23f0ef13bba895388ae93 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 21:05:32 +0300 Subject: [PATCH 06/11] Add docs --- docs/03_Usage.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/03_Usage.md b/docs/03_Usage.md index c115a841..b538db0f 100644 --- a/docs/03_Usage.md +++ b/docs/03_Usage.md @@ -52,3 +52,50 @@ More info can be found in [here](https://docs.sqlc.dev/en/stable/reference/query | sqlc.embed | ✅ | ✅ | ✅ | More info can be found in [here](https://docs.sqlc.dev/en/stable/reference/macros.html#macros). + + +### Transactions +Transactions are supported by the plugin. +
+ +| Feature | PostgresSQL | MySQL | SQLite | +|-------------|-------------|-------|---------| +| Transactions| ✅ | ✅ | ✅ | + +#### Example using a transaction +```c# +public async Task ExampleTransaction(IDbConnection connection) +{ + // Begin a transaction + using (var transaction = connection.BeginTransaction()) + { + try + { + // Create a new Queries object with the transaction instead of the connection + var queries = new QuerySql(transaction); + + // Example: Insert a new author + var newAuthor = await queries.CreateAuthor(new CreateAuthorParams { Name = "Jane Doe", Bio = "Another author" }); + + // Example: Get the author by ID within the same transaction + var author = await queries.GetAuthor(newAuthor.AuthorID); + + // Example: Update the author's bio + await queries.UpdateAuthorBio(new UpdateAuthorBioParams { AuthorID = author.AuthorID, Bio = "Updated bio for Jane Doe" }); + + // Commit the transaction if all operations are successful + transaction.Commit(); + Console.WriteLine("Transaction committed successfully."); + } + catch (Exception ex) + { + // Rollback the transaction if any error occurs + transaction.Rollback(); + Console.WriteLine($"Transaction rolled back due to error: {ex.Message}"); + throw; + } + } +} +``` + +More info can be found in [here](https://docs.sqlc.dev/en/stable/howto/transactions.html). \ No newline at end of file From 1b5191fe627136bc58e27b3e58fe3c05d31ca96e Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 21:09:01 +0300 Subject: [PATCH 07/11] fix tests --- end2end/EndToEndScaffold/Templates/SqliteTests.cs | 2 +- end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs | 4 ++-- end2end/EndToEndTestsLegacy/SqliteTester.generated.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/end2end/EndToEndScaffold/Templates/SqliteTests.cs b/end2end/EndToEndScaffold/Templates/SqliteTests.cs index d1c7f075..a01a69cf 100644 --- a/end2end/EndToEndScaffold/Templates/SqliteTests.cs +++ b/end2end/EndToEndScaffold/Templates/SqliteTests.cs @@ -106,7 +106,7 @@ public async Task TestSqliteTransaction() var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types - await transaction.CommitAsync(); + transaction.Commit(); var expected = new QuerySql.GetAuthorRow { diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs index 24b679c6..5ca1fdd3 100644 --- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs @@ -369,7 +369,7 @@ public async Task TestSqliteTransaction() // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types - await transaction.CommitAsync(); + transaction.Commit(); var expected = new QuerySql.GetAuthorRow { Id = 1111, @@ -380,4 +380,4 @@ public async Task TestSqliteTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } } -} +} diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs index a4d4876d..52ac9ee3 100644 --- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs @@ -369,7 +369,7 @@ public async Task TestSqliteTransaction() // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types - await transaction.CommitAsync(); + transaction.Commit(); var expected = new QuerySql.GetAuthorRow { Id = 1111, @@ -380,4 +380,4 @@ public async Task TestSqliteTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } } -} +} From 6a0ede65edd63ae3188c93d4292105f58873a151 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 25 Jun 2025 21:13:00 +0300 Subject: [PATCH 08/11] fix tests --- end2end/EndToEndTests/SqliteDapperTester.generated.cs | 2 +- end2end/EndToEndTests/SqliteTester.generated.cs | 2 +- end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs | 2 +- end2end/EndToEndTestsLegacy/SqliteTester.generated.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/end2end/EndToEndTests/SqliteDapperTester.generated.cs b/end2end/EndToEndTests/SqliteDapperTester.generated.cs index e43f6145..64d7784e 100644 --- a/end2end/EndToEndTests/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTests/SqliteDapperTester.generated.cs @@ -369,7 +369,7 @@ public async Task TestSqliteTransaction() // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types - await transaction.CommitAsync(); + transaction.Commit(); var expected = new QuerySql.GetAuthorRow { Id = 1111, diff --git a/end2end/EndToEndTests/SqliteTester.generated.cs b/end2end/EndToEndTests/SqliteTester.generated.cs index 85b7ea2f..5a726681 100644 --- a/end2end/EndToEndTests/SqliteTester.generated.cs +++ b/end2end/EndToEndTests/SqliteTester.generated.cs @@ -369,7 +369,7 @@ public async Task TestSqliteTransaction() // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types - await transaction.CommitAsync(); + transaction.Commit(); var expected = new QuerySql.GetAuthorRow { Id = 1111, diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs index 5ca1fdd3..27f1453b 100644 --- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs @@ -380,4 +380,4 @@ public async Task TestSqliteTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } } -} +} diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs index 52ac9ee3..eb7086d1 100644 --- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs @@ -380,4 +380,4 @@ public async Task TestSqliteTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } } -} +} From fa9f36598b5c59a8d92096c5ef220027fb911ef5 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 2 Jul 2025 23:11:49 +0300 Subject: [PATCH 09/11] change the way we create query sql with transaction --- CodeGenerator/Generators/QueriesGen.cs | 7 ++++++- docs/03_Usage.md | 2 +- end2end/EndToEndScaffold/Templates/MySqlTests.cs | 2 +- end2end/EndToEndScaffold/Templates/PostgresTests.cs | 2 +- end2end/EndToEndScaffold/Templates/SqliteTests.cs | 2 +- .../EndToEndTests/MySqlConnectorDapperTester.generated.cs | 2 +- end2end/EndToEndTests/MySqlConnectorTester.generated.cs | 2 +- end2end/EndToEndTests/NpgsqlDapperTester.generated.cs | 2 +- end2end/EndToEndTests/NpgsqlTester.generated.cs | 2 +- end2end/EndToEndTests/SqliteDapperTester.generated.cs | 2 +- end2end/EndToEndTests/SqliteTester.generated.cs | 2 +- .../MySqlConnectorDapperTester.generated.cs | 2 +- .../EndToEndTestsLegacy/MySqlConnectorTester.generated.cs | 2 +- .../EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs | 2 +- end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs | 2 +- .../EndToEndTestsLegacy/SqliteDapperTester.generated.cs | 2 +- end2end/EndToEndTestsLegacy/SqliteTester.generated.cs | 2 +- examples/MySqlConnectorDapperExample/QuerySql.cs | 7 ++++++- examples/MySqlConnectorDapperLegacyExample/QuerySql.cs | 7 ++++++- examples/MySqlConnectorExample/QuerySql.cs | 7 ++++++- examples/MySqlConnectorLegacyExample/QuerySql.cs | 7 ++++++- examples/NpgsqlDapperExample/QuerySql.cs | 7 ++++++- examples/NpgsqlDapperLegacyExample/QuerySql.cs | 7 ++++++- examples/NpgsqlExample/QuerySql.cs | 7 ++++++- examples/NpgsqlLegacyExample/QuerySql.cs | 7 ++++++- examples/SqliteDapperExample/QuerySql.cs | 7 ++++++- examples/SqliteDapperLegacyExample/QuerySql.cs | 7 ++++++- examples/SqliteExample/QuerySql.cs | 7 ++++++- examples/SqliteLegacyExample/QuerySql.cs | 7 ++++++- 29 files changed, 94 insertions(+), 29 deletions(-) diff --git a/CodeGenerator/Generators/QueriesGen.cs b/CodeGenerator/Generators/QueriesGen.cs index 917bf89d..ddafb45e 100644 --- a/CodeGenerator/Generators/QueriesGen.cs +++ b/CodeGenerator/Generators/QueriesGen.cs @@ -65,11 +65,16 @@ public class {{className}} {{dbDriver.GetConstructorStatements().JoinByNewLine()}} } - public {{className}}({{dbDriver.TransactionClassName}} {{Variable.Transaction.AsVarName()}}) + private {{className}}({{dbDriver.TransactionClassName}} {{Variable.Transaction.AsVarName()}}) { {{dbDriver.GetTransactionConstructorStatements().JoinByNewLine()}} } + public static {{className}} WithTransaction({{dbDriver.TransactionClassName}} {{Variable.Transaction.AsVarName()}}) + { + return new {{className}}({{Variable.Transaction.AsVarName()}}); + } + private {{dbDriver.AddNullableSuffixIfNeeded(dbDriver.TransactionClassName, false)}} {{Variable.Transaction.AsPropertyName()}} { get; } private {{dbDriver.AddNullableSuffixIfNeeded("string", false)}} {{Variable.ConnectionString.AsPropertyName()}} { get; } } diff --git a/docs/03_Usage.md b/docs/03_Usage.md index b538db0f..5837eafc 100644 --- a/docs/03_Usage.md +++ b/docs/03_Usage.md @@ -72,7 +72,7 @@ public async Task ExampleTransaction(IDbConnection connection) try { // Create a new Queries object with the transaction instead of the connection - var queries = new QuerySql(transaction); + var queries = QuerySql.WithTransaction(transaction); // Example: Insert a new author var newAuthor = await queries.CreateAuthor(new CreateAuthorParams { Name = "Jane Doe", Bio = "Another author" }); diff --git a/end2end/EndToEndScaffold/Templates/MySqlTests.cs b/end2end/EndToEndScaffold/Templates/MySqlTests.cs index 7d1c2320..f689d1cb 100644 --- a/end2end/EndToEndScaffold/Templates/MySqlTests.cs +++ b/end2end/EndToEndScaffold/Templates/MySqlTests.cs @@ -533,7 +533,7 @@ public async Task TestMySqlTransaction() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndScaffold/Templates/PostgresTests.cs b/end2end/EndToEndScaffold/Templates/PostgresTests.cs index 1b67d331..a8a4376d 100644 --- a/end2end/EndToEndScaffold/Templates/PostgresTests.cs +++ b/end2end/EndToEndScaffold/Templates/PostgresTests.cs @@ -494,7 +494,7 @@ public async Task TestPostgresTransaction() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) diff --git a/end2end/EndToEndScaffold/Templates/SqliteTests.cs b/end2end/EndToEndScaffold/Templates/SqliteTests.cs index cc9c5078..4c166993 100644 --- a/end2end/EndToEndScaffold/Templates/SqliteTests.cs +++ b/end2end/EndToEndScaffold/Templates/SqliteTests.cs @@ -99,7 +99,7 @@ public async Task TestSqliteTransaction() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index b3b286a7..b0e03e42 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -367,7 +367,7 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types diff --git a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs index 78d9aebe..332fcb74 100644 --- a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs @@ -367,7 +367,7 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types diff --git a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs index 884942b2..61412366 100644 --- a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs @@ -441,7 +441,7 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTests/NpgsqlTester.generated.cs b/end2end/EndToEndTests/NpgsqlTester.generated.cs index 731e020f..025dc5e6 100644 --- a/end2end/EndToEndTests/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlTester.generated.cs @@ -441,7 +441,7 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTests/SqliteDapperTester.generated.cs b/end2end/EndToEndTests/SqliteDapperTester.generated.cs index f20113b2..cd4ec69b 100644 --- a/end2end/EndToEndTests/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTests/SqliteDapperTester.generated.cs @@ -387,7 +387,7 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTests/SqliteTester.generated.cs b/end2end/EndToEndTests/SqliteTester.generated.cs index c01d654c..eebbee24 100644 --- a/end2end/EndToEndTests/SqliteTester.generated.cs +++ b/end2end/EndToEndTests/SqliteTester.generated.cs @@ -387,7 +387,7 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs index d29ea9c8..a95c287e 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs @@ -367,7 +367,7 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs index b6c64a0e..7ab61cb4 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs @@ -367,7 +367,7 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types diff --git a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs index 57c8edf4..1efbf75c 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs @@ -441,7 +441,7 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs index 78caeecc..632b98bf 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs @@ -441,7 +441,7 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs index adff3176..fd4eb5ed 100644 --- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs @@ -387,7 +387,7 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs index 5d2dfe0d..2acf0633 100644 --- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs @@ -387,7 +387,7 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = new QuerySql(transaction); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); diff --git a/examples/MySqlConnectorDapperExample/QuerySql.cs b/examples/MySqlConnectorDapperExample/QuerySql.cs index 0cdafcbd..de07ffba 100644 --- a/examples/MySqlConnectorDapperExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperExample/QuerySql.cs @@ -25,12 +25,17 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - public QuerySql(MySqlTransaction transaction) + private QuerySql(MySqlTransaction transaction) { this.Transaction = transaction; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } + public static QuerySql WithTransaction(MySqlTransaction transaction) + { + return new QuerySql(transaction); + } + private MySqlTransaction? Transaction { get; } private string? ConnectionString { get; } diff --git a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs index 75ec6685..70a6f361 100644 --- a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs @@ -26,12 +26,17 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - public QuerySql(MySqlTransaction transaction) + private QuerySql(MySqlTransaction transaction) { this.Transaction = transaction; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } + public static QuerySql WithTransaction(MySqlTransaction transaction) + { + return new QuerySql(transaction); + } + private MySqlTransaction Transaction { get; } private string ConnectionString { get; } diff --git a/examples/MySqlConnectorExample/QuerySql.cs b/examples/MySqlConnectorExample/QuerySql.cs index 6ad82088..e76bfb30 100644 --- a/examples/MySqlConnectorExample/QuerySql.cs +++ b/examples/MySqlConnectorExample/QuerySql.cs @@ -23,11 +23,16 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - public QuerySql(MySqlTransaction transaction) + private QuerySql(MySqlTransaction transaction) { this.Transaction = transaction; } + public static QuerySql WithTransaction(MySqlTransaction transaction) + { + return new QuerySql(transaction); + } + private MySqlTransaction? Transaction { get; } private string? ConnectionString { get; } diff --git a/examples/MySqlConnectorLegacyExample/QuerySql.cs b/examples/MySqlConnectorLegacyExample/QuerySql.cs index 7281541e..d81c4d13 100644 --- a/examples/MySqlConnectorLegacyExample/QuerySql.cs +++ b/examples/MySqlConnectorLegacyExample/QuerySql.cs @@ -24,11 +24,16 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - public QuerySql(MySqlTransaction transaction) + private QuerySql(MySqlTransaction transaction) { this.Transaction = transaction; } + public static QuerySql WithTransaction(MySqlTransaction transaction) + { + return new QuerySql(transaction); + } + private MySqlTransaction Transaction { get; } private string ConnectionString { get; } diff --git a/examples/NpgsqlDapperExample/QuerySql.cs b/examples/NpgsqlDapperExample/QuerySql.cs index c5557c32..f2464c6b 100644 --- a/examples/NpgsqlDapperExample/QuerySql.cs +++ b/examples/NpgsqlDapperExample/QuerySql.cs @@ -22,13 +22,18 @@ public QuerySql(string connectionString) Utils.ConfigureSqlMapper(); } - public QuerySql(NpgsqlTransaction transaction) + private QuerySql(NpgsqlTransaction transaction) { this.Transaction = transaction; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; Utils.ConfigureSqlMapper(); } + public static QuerySql WithTransaction(NpgsqlTransaction transaction) + { + return new QuerySql(transaction); + } + private NpgsqlTransaction? Transaction { get; } private string? ConnectionString { get; } diff --git a/examples/NpgsqlDapperLegacyExample/QuerySql.cs b/examples/NpgsqlDapperLegacyExample/QuerySql.cs index 5384151d..46a99015 100644 --- a/examples/NpgsqlDapperLegacyExample/QuerySql.cs +++ b/examples/NpgsqlDapperLegacyExample/QuerySql.cs @@ -23,13 +23,18 @@ public QuerySql(string connectionString) Utils.ConfigureSqlMapper(); } - public QuerySql(NpgsqlTransaction transaction) + private QuerySql(NpgsqlTransaction transaction) { this.Transaction = transaction; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; Utils.ConfigureSqlMapper(); } + public static QuerySql WithTransaction(NpgsqlTransaction transaction) + { + return new QuerySql(transaction); + } + private NpgsqlTransaction Transaction { get; } private string ConnectionString { get; } diff --git a/examples/NpgsqlExample/QuerySql.cs b/examples/NpgsqlExample/QuerySql.cs index b53883ad..65c3f355 100644 --- a/examples/NpgsqlExample/QuerySql.cs +++ b/examples/NpgsqlExample/QuerySql.cs @@ -19,11 +19,16 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - public QuerySql(NpgsqlTransaction transaction) + private QuerySql(NpgsqlTransaction transaction) { this.Transaction = transaction; } + public static QuerySql WithTransaction(NpgsqlTransaction transaction) + { + return new QuerySql(transaction); + } + private NpgsqlTransaction? Transaction { get; } private string? ConnectionString { get; } diff --git a/examples/NpgsqlLegacyExample/QuerySql.cs b/examples/NpgsqlLegacyExample/QuerySql.cs index 094535c1..5344de2c 100644 --- a/examples/NpgsqlLegacyExample/QuerySql.cs +++ b/examples/NpgsqlLegacyExample/QuerySql.cs @@ -20,11 +20,16 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - public QuerySql(NpgsqlTransaction transaction) + private QuerySql(NpgsqlTransaction transaction) { this.Transaction = transaction; } + public static QuerySql WithTransaction(NpgsqlTransaction transaction) + { + return new QuerySql(transaction); + } + private NpgsqlTransaction Transaction { get; } private string ConnectionString { get; } diff --git a/examples/SqliteDapperExample/QuerySql.cs b/examples/SqliteDapperExample/QuerySql.cs index c5ece2f3..fd122ba8 100644 --- a/examples/SqliteDapperExample/QuerySql.cs +++ b/examples/SqliteDapperExample/QuerySql.cs @@ -19,12 +19,17 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - public QuerySql(SqliteTransaction transaction) + private QuerySql(SqliteTransaction transaction) { this.Transaction = transaction; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } + public static QuerySql WithTransaction(SqliteTransaction transaction) + { + return new QuerySql(transaction); + } + private SqliteTransaction? Transaction { get; } private string? ConnectionString { get; } diff --git a/examples/SqliteDapperLegacyExample/QuerySql.cs b/examples/SqliteDapperLegacyExample/QuerySql.cs index 6c9894ca..bdd92601 100644 --- a/examples/SqliteDapperLegacyExample/QuerySql.cs +++ b/examples/SqliteDapperLegacyExample/QuerySql.cs @@ -20,12 +20,17 @@ public QuerySql(string connectionString) Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } - public QuerySql(SqliteTransaction transaction) + private QuerySql(SqliteTransaction transaction) { this.Transaction = transaction; Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; } + public static QuerySql WithTransaction(SqliteTransaction transaction) + { + return new QuerySql(transaction); + } + private SqliteTransaction Transaction { get; } private string ConnectionString { get; } diff --git a/examples/SqliteExample/QuerySql.cs b/examples/SqliteExample/QuerySql.cs index 164ba1de..5ef332d4 100644 --- a/examples/SqliteExample/QuerySql.cs +++ b/examples/SqliteExample/QuerySql.cs @@ -17,11 +17,16 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - public QuerySql(SqliteTransaction transaction) + private QuerySql(SqliteTransaction transaction) { this.Transaction = transaction; } + public static QuerySql WithTransaction(SqliteTransaction transaction) + { + return new QuerySql(transaction); + } + private SqliteTransaction? Transaction { get; } private string? ConnectionString { get; } diff --git a/examples/SqliteLegacyExample/QuerySql.cs b/examples/SqliteLegacyExample/QuerySql.cs index 55617da4..a2ff5900 100644 --- a/examples/SqliteLegacyExample/QuerySql.cs +++ b/examples/SqliteLegacyExample/QuerySql.cs @@ -18,11 +18,16 @@ public QuerySql(string connectionString) this.ConnectionString = connectionString; } - public QuerySql(SqliteTransaction transaction) + private QuerySql(SqliteTransaction transaction) { this.Transaction = transaction; } + public static QuerySql WithTransaction(SqliteTransaction transaction) + { + return new QuerySql(transaction); + } + private SqliteTransaction Transaction { get; } private string ConnectionString { get; } From 72142d96c4048e1efbe6cfa7aa9dccb91eb8ac27 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Wed, 2 Jul 2025 23:26:41 +0300 Subject: [PATCH 10/11] add rollback test --- end2end/EndToEndScaffold/Config.cs | 9 +++++++++ .../EndToEndScaffold/Templates/MySqlTests.cs | 20 +++++++++++++++++++ .../Templates/PostgresTests.cs | 20 +++++++++++++++++++ .../EndToEndScaffold/Templates/SqliteTests.cs | 20 +++++++++++++++++++ .../MySqlConnectorDapperTester.generated.cs | 13 ++++++++++++ .../MySqlConnectorTester.generated.cs | 13 ++++++++++++ .../NpgsqlDapperTester.generated.cs | 13 ++++++++++++ .../EndToEndTests/NpgsqlTester.generated.cs | 13 ++++++++++++ .../SqliteDapperTester.generated.cs | 13 ++++++++++++ .../EndToEndTests/SqliteTester.generated.cs | 13 ++++++++++++ .../MySqlConnectorDapperTester.generated.cs | 13 ++++++++++++ .../MySqlConnectorTester.generated.cs | 13 ++++++++++++ .../NpgsqlDapperTester.generated.cs | 13 ++++++++++++ .../NpgsqlTester.generated.cs | 13 ++++++++++++ .../SqliteDapperTester.generated.cs | 13 ++++++++++++ .../SqliteTester.generated.cs | 13 ++++++++++++ 16 files changed, 225 insertions(+) diff --git a/end2end/EndToEndScaffold/Config.cs b/end2end/EndToEndScaffold/Config.cs index ae72f1ac..77f4b52f 100644 --- a/end2end/EndToEndScaffold/Config.cs +++ b/end2end/EndToEndScaffold/Config.cs @@ -31,6 +31,7 @@ public enum KnownTestType SqliteDataTypesOverride, SqliteCopyFrom, SqliteTransaction, + SqliteTransactionRollback, // Postgres PostgresStringDataTypes, @@ -42,6 +43,7 @@ public enum KnownTestType PostgresStringCopyFrom, PostgresTransaction, + PostgresTransactionRollback, PostgresIntegerCopyFrom, PostgresFloatingPointCopyFrom, PostgresDateTimeCopyFrom, @@ -55,6 +57,7 @@ public enum KnownTestType MySqlStringDataTypes, MySqlIntegerDataTypes, MySqlTransaction, + MySqlTransactionRollback, MySqlFloatingPointDataTypes, MySqlDateTimeDataTypes, MySqlBinaryDataTypes, @@ -96,6 +99,7 @@ internal static class Config KnownTestType.MySqlStringDataTypes, KnownTestType.MySqlIntegerDataTypes, KnownTestType.MySqlTransaction, + KnownTestType.MySqlTransactionRollback, KnownTestType.MySqlFloatingPointDataTypes, KnownTestType.MySqlDateTimeDataTypes, KnownTestType.MySqlBinaryDataTypes, @@ -133,6 +137,7 @@ internal static class Config KnownTestType.MySqlStringDataTypes, KnownTestType.MySqlIntegerDataTypes, KnownTestType.MySqlTransaction, + KnownTestType.MySqlTransactionRollback, KnownTestType.MySqlFloatingPointDataTypes, KnownTestType.MySqlDateTimeDataTypes, KnownTestType.MySqlBinaryDataTypes, @@ -168,6 +173,7 @@ internal static class Config KnownTestType.NargNotNull, KnownTestType.PostgresTransaction, + KnownTestType.PostgresTransactionRollback, KnownTestType.PostgresStringDataTypes, KnownTestType.PostgresIntegerDataTypes, KnownTestType.PostgresFloatingPointDataTypes, @@ -202,6 +208,7 @@ internal static class Config KnownTestType.NargNull, KnownTestType.NargNotNull, KnownTestType.PostgresTransaction, + KnownTestType.PostgresTransactionRollback, KnownTestType.PostgresStringDataTypes, KnownTestType.PostgresIntegerDataTypes, @@ -237,6 +244,7 @@ internal static class Config KnownTestType.NargNull, KnownTestType.NargNotNull, KnownTestType.SqliteTransaction, + KnownTestType.SqliteTransactionRollback, KnownTestType.SqliteDataTypes, KnownTestType.SqliteCopyFrom, KnownTestType.SqliteDataTypesOverride @@ -261,6 +269,7 @@ internal static class Config KnownTestType.NargNull, KnownTestType.NargNotNull, KnownTestType.SqliteTransaction, + KnownTestType.SqliteTransactionRollback, KnownTestType.SqliteDataTypes, KnownTestType.SqliteCopyFrom, KnownTestType.SqliteDataTypesOverride diff --git a/end2end/EndToEndScaffold/Templates/MySqlTests.cs b/end2end/EndToEndScaffold/Templates/MySqlTests.cs index f689d1cb..38ec69f7 100644 --- a/end2end/EndToEndScaffold/Templates/MySqlTests.cs +++ b/end2end/EndToEndScaffold/Templates/MySqlTests.cs @@ -552,6 +552,26 @@ public async Task TestMySqlTransaction() } """ }, + [KnownTestType.MySqlTransactionRollback] = new TestImpl + { + Impl = $$""" + [Test] + public async Task TestMySqlTransactionRollback() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + await transaction.RollbackAsync(); + + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + """ + }, [KnownTestType.MySqlEnumCopyFrom] = new TestImpl { Impl = $$""" diff --git a/end2end/EndToEndScaffold/Templates/PostgresTests.cs b/end2end/EndToEndScaffold/Templates/PostgresTests.cs index a8a4376d..0b4db68a 100644 --- a/end2end/EndToEndScaffold/Templates/PostgresTests.cs +++ b/end2end/EndToEndScaffold/Templates/PostgresTests.cs @@ -514,6 +514,26 @@ public async Task TestPostgresTransaction() } """ }, + [KnownTestType.PostgresTransactionRollback] = new TestImpl + { + Impl = $$""" + [Test] + public async Task TestPostgresTransactionRollback() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + await transaction.RollbackAsync(); + + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + """ + }, [KnownTestType.PostgresDataTypesOverride] = new TestImpl { Impl = $$""" diff --git a/end2end/EndToEndScaffold/Templates/SqliteTests.cs b/end2end/EndToEndScaffold/Templates/SqliteTests.cs index 4c166993..a80249a6 100644 --- a/end2end/EndToEndScaffold/Templates/SqliteTests.cs +++ b/end2end/EndToEndScaffold/Templates/SqliteTests.cs @@ -119,6 +119,26 @@ public async Task TestSqliteTransaction() } """ }, + [KnownTestType.SqliteTransactionRollback] = new TestImpl + { + Impl = $$""" + [Test] + public async Task TestSqliteTransactionRollback() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + + transaction.Rollback(); + + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + """ + }, [KnownTestType.SqliteDataTypesOverride] = new TestImpl { Impl = $$""" diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index b0e03e42..a3119841 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -382,6 +382,19 @@ public async Task TestMySqlTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + [Test] + public async Task TestMySqlTransactionRollback() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs index 332fcb74..3d962dd4 100644 --- a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs @@ -382,6 +382,19 @@ public async Task TestMySqlTransaction() Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here } + [Test] + public async Task TestMySqlTransactionRollback() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs index 61412366..8c1f0916 100644 --- a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs @@ -457,6 +457,19 @@ public async Task TestPostgresTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + [Test] + public async Task TestPostgresTransactionRollback() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTests/NpgsqlTester.generated.cs b/end2end/EndToEndTests/NpgsqlTester.generated.cs index 025dc5e6..9ad572bb 100644 --- a/end2end/EndToEndTests/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlTester.generated.cs @@ -457,6 +457,19 @@ public async Task TestPostgresTransaction() Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here } + [Test] + public async Task TestPostgresTransactionRollback() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTests/SqliteDapperTester.generated.cs b/end2end/EndToEndTests/SqliteDapperTester.generated.cs index cd4ec69b..727e2479 100644 --- a/end2end/EndToEndTests/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTests/SqliteDapperTester.generated.cs @@ -402,5 +402,18 @@ public async Task TestSqliteTransaction() var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + + [Test] + public async Task TestSqliteTransactionRollback() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + transaction.Rollback(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } } } diff --git a/end2end/EndToEndTests/SqliteTester.generated.cs b/end2end/EndToEndTests/SqliteTester.generated.cs index eebbee24..23910fbd 100644 --- a/end2end/EndToEndTests/SqliteTester.generated.cs +++ b/end2end/EndToEndTests/SqliteTester.generated.cs @@ -402,5 +402,18 @@ public async Task TestSqliteTransaction() var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here } + + [Test] + public async Task TestSqliteTransactionRollback() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + transaction.Rollback(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } } } diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs index a95c287e..5a9414c8 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs @@ -382,6 +382,19 @@ public async Task TestMySqlTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + [Test] + public async Task TestMySqlTransactionRollback() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs index 7ab61cb4..62240b92 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs @@ -382,6 +382,19 @@ public async Task TestMySqlTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + [Test] + public async Task TestMySqlTransactionRollback() + { + var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534)] [TestCase(null, null, null, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs index 1efbf75c..f4de318d 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs @@ -457,6 +457,19 @@ public async Task TestPostgresTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + [Test] + public async Task TestPostgresTransactionRollback() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs index 632b98bf..a9a285b8 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs @@ -457,6 +457,19 @@ public async Task TestPostgresTransaction() Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + [Test] + public async Task TestPostgresTransactionRollback() + { + var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await transaction.RollbackAsync(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } + [Test] [TestCase(100, true, 3, 453, -1445214231L)] [TestCase(10, null, null, null, null)] diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs index fd4eb5ed..d5e5e4e0 100644 --- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs @@ -402,5 +402,18 @@ public async Task TestSqliteTransaction() var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + + [Test] + public async Task TestSqliteTransactionRollback() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + transaction.Rollback(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } } } diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs index 2acf0633..b8891025 100644 --- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs @@ -402,5 +402,18 @@ public async Task TestSqliteTransaction() var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } + + [Test] + public async Task TestSqliteTransactionRollback() + { + var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); + await connection.OpenAsync(); + var transaction = connection.BeginTransaction(); + var sqlQueryWithTx = QuerySql.WithTransaction(transaction); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + transaction.Rollback(); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + Assert.That(actual == null, "author should not exist after rollback"); + } } } From 3026e2efcd246d38cdaec2c7185443170ae4a481 Mon Sep 17 00:00:00 2001 From: Doron Eli Rachman Date: Fri, 4 Jul 2025 00:58:19 +0300 Subject: [PATCH 11/11] fix PR comments --- docs/03_Usage.md | 6 +----- .../EndToEndScaffold/Templates/MySqlTests.cs | 20 +++++++++---------- .../Templates/PostgresTests.cs | 18 ++++++++--------- .../EndToEndScaffold/Templates/SqliteTests.cs | 18 ++++++++--------- .../MySqlConnectorDapperTester.generated.cs | 14 ++++++------- .../MySqlConnectorTester.generated.cs | 14 ++++++------- .../NpgsqlDapperTester.generated.cs | 10 +++++----- .../EndToEndTests/NpgsqlTester.generated.cs | 10 +++++----- .../SqliteDapperTester.generated.cs | 8 ++++---- .../EndToEndTests/SqliteTester.generated.cs | 8 ++++---- .../MySqlConnectorDapperTester.generated.cs | 14 ++++++------- .../MySqlConnectorTester.generated.cs | 14 ++++++------- .../NpgsqlDapperTester.generated.cs | 10 +++++----- .../NpgsqlTester.generated.cs | 10 +++++----- .../SqliteDapperTester.generated.cs | 8 ++++---- .../SqliteTester.generated.cs | 8 ++++---- 16 files changed, 93 insertions(+), 97 deletions(-) diff --git a/docs/03_Usage.md b/docs/03_Usage.md index 56d8b597..0df33541 100644 --- a/docs/03_Usage.md +++ b/docs/03_Usage.md @@ -68,12 +68,8 @@ More info can be found in [here](https://docs.sqlc.dev/en/stable/reference/macro Transactions are supported by the plugin.
-| Feature | PostgresSQL | MySQL | SQLite | -|-------------|-------------|-------|---------| -| Transactions| ✅ | ✅ | ✅ | - #### Example using a transaction -```c# +```C# public async Task ExampleTransaction(IDbConnection connection) { // Begin a transaction diff --git a/end2end/EndToEndScaffold/Templates/MySqlTests.cs b/end2end/EndToEndScaffold/Templates/MySqlTests.cs index 38ec69f7..01f76de8 100644 --- a/end2end/EndToEndScaffold/Templates/MySqlTests.cs +++ b/end2end/EndToEndScaffold/Templates/MySqlTests.cs @@ -533,21 +533,21 @@ public async Task TestMySqlTransaction() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = {{Consts.BojackId}}, Name = {{Consts.BojackAuthor}}, Bio = {{Consts.BojackTheme}} }); - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow { - Id = 1111, - Name = "Bojack Horseman", - Bio = "Back in the 90s he was in a very famous TV show" + Id = {{Consts.BojackId}}, + Name = {{Consts.BojackAuthor}}, + Bio = {{Consts.BojackTheme}} }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(SingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}})); // Apply placeholder here } """ @@ -562,12 +562,12 @@ public async Task TestMySqlTransactionRollback() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = {{Consts.BojackId}}, Name = {{Consts.BojackAuthor}}, Bio = {{Consts.BojackTheme}} }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(actual == null, "author should not exist after rollback"); } """ diff --git a/end2end/EndToEndScaffold/Templates/PostgresTests.cs b/end2end/EndToEndScaffold/Templates/PostgresTests.cs index 0b4db68a..8a0b04e7 100644 --- a/end2end/EndToEndScaffold/Templates/PostgresTests.cs +++ b/end2end/EndToEndScaffold/Templates/PostgresTests.cs @@ -494,22 +494,22 @@ public async Task TestPostgresTransaction() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = {{Consts.BojackId}}, Name = {{Consts.BojackAuthor}}, Bio = {{Consts.BojackTheme}} }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow { - Id = 1111, - Name = "Bojack Horseman", - Bio = "Back in the 90s he was in a very famous TV show" + Id = {{Consts.BojackId}}, + Name = {{Consts.BojackAuthor}}, + Bio = {{Consts.BojackTheme}} }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(SingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}})); // Apply placeholder here } """ @@ -525,11 +525,11 @@ public async Task TestPostgresTransactionRollback() var transaction = connection.BeginTransaction(); var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = {{Consts.BojackId}}, Name = {{Consts.BojackAuthor}}, Bio = {{Consts.BojackTheme}} }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(actual == null, "author should not exist after rollback"); } """ diff --git a/end2end/EndToEndScaffold/Templates/SqliteTests.cs b/end2end/EndToEndScaffold/Templates/SqliteTests.cs index a80249a6..03f6f8c0 100644 --- a/end2end/EndToEndScaffold/Templates/SqliteTests.cs +++ b/end2end/EndToEndScaffold/Templates/SqliteTests.cs @@ -99,22 +99,22 @@ public async Task TestSqliteTransaction() await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = {{Consts.BojackId}}, Name = {{Consts.BojackAuthor}}, Bio = {{Consts.BojackTheme}} }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types transaction.Commit(); var expected = new QuerySql.GetAuthorRow { - Id = 1111, - Name = "Bojack Horseman", - Bio = "Back in the 90s he was in a very famous TV show" + Id = {{Consts.BojackId}}, + Name = {{Consts.BojackAuthor}}, + Bio = {{Consts.BojackTheme}} }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(SingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}})); // Apply placeholder here } """ @@ -130,11 +130,11 @@ public async Task TestSqliteTransactionRollback() var transaction = connection.BeginTransaction(); var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = {{Consts.BojackId}}, Name = {{Consts.BojackAuthor}}, Bio = {{Consts.BojackTheme}} }); transaction.Rollback(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = {{Consts.BojackAuthor}} }); Assert.That(actual == null, "author should not exist after rollback"); } """ diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs index a3119841..7d3a55a0 100644 --- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs @@ -367,9 +367,9 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -378,7 +378,7 @@ public async Task TestMySqlTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } @@ -388,10 +388,10 @@ public async Task TestMySqlTransactionRollback() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs index 3d962dd4..df9a4c6d 100644 --- a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs @@ -367,9 +367,9 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -378,7 +378,7 @@ public async Task TestMySqlTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here } @@ -388,10 +388,10 @@ public async Task TestMySqlTransactionRollback() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs index 8c1f0916..636a4606 100644 --- a/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlDapperTester.generated.cs @@ -441,10 +441,10 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -453,7 +453,7 @@ public async Task TestPostgresTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } @@ -466,7 +466,7 @@ public async Task TestPostgresTransactionRollback() var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTests/NpgsqlTester.generated.cs b/end2end/EndToEndTests/NpgsqlTester.generated.cs index 9ad572bb..1facb2b7 100644 --- a/end2end/EndToEndTests/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTests/NpgsqlTester.generated.cs @@ -441,10 +441,10 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -453,7 +453,7 @@ public async Task TestPostgresTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here } @@ -466,7 +466,7 @@ public async Task TestPostgresTransactionRollback() var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTests/SqliteDapperTester.generated.cs b/end2end/EndToEndTests/SqliteDapperTester.generated.cs index 727e2479..64a4dee5 100644 --- a/end2end/EndToEndTests/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTests/SqliteDapperTester.generated.cs @@ -387,10 +387,10 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types transaction.Commit(); var expected = new QuerySql.GetAuthorRow @@ -399,7 +399,7 @@ public async Task TestSqliteTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } diff --git a/end2end/EndToEndTests/SqliteTester.generated.cs b/end2end/EndToEndTests/SqliteTester.generated.cs index 23910fbd..e4c7aad5 100644 --- a/end2end/EndToEndTests/SqliteTester.generated.cs +++ b/end2end/EndToEndTests/SqliteTester.generated.cs @@ -387,10 +387,10 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types transaction.Commit(); var expected = new QuerySql.GetAuthorRow @@ -399,7 +399,7 @@ public async Task TestSqliteTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual.Value)); // Apply placeholder here } diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs index 5a9414c8..98e738b9 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs @@ -367,9 +367,9 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -378,7 +378,7 @@ public async Task TestMySqlTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } @@ -388,10 +388,10 @@ public async Task TestMySqlTransactionRollback() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs index 62240b92..8085b93a 100644 --- a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs @@ -367,9 +367,9 @@ public async Task TestMySqlTransaction() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -378,7 +378,7 @@ public async Task TestMySqlTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } @@ -388,10 +388,10 @@ public async Task TestMySqlTransactionRollback() var connection = new MySqlConnector.MySqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.MySqlConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs index f4de318d..79ed9b8b 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs @@ -441,10 +441,10 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -453,7 +453,7 @@ public async Task TestPostgresTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } @@ -466,7 +466,7 @@ public async Task TestPostgresTransactionRollback() var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs index a9a285b8..df9725f6 100644 --- a/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs @@ -441,10 +441,10 @@ public async Task TestPostgresTransaction() var connection = new Npgsql.NpgsqlConnection(Environment.GetEnvironmentVariable(EndToEndCommon.PostgresConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in NpgsqlExampleGen returns QuerySql.GetAuthorRow? (nullable record struct) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types await transaction.CommitAsync(); var expected = new QuerySql.GetAuthorRow @@ -453,7 +453,7 @@ public async Task TestPostgresTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } @@ -466,7 +466,7 @@ public async Task TestPostgresTransactionRollback() var sqlQueryWithTx = QuerySql.WithTransaction(transaction); await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); await transaction.RollbackAsync(); - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actual == null, "author should not exist after rollback"); } diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs index d5e5e4e0..64ef7e14 100644 --- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs @@ -387,10 +387,10 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types transaction.Commit(); var expected = new QuerySql.GetAuthorRow @@ -399,7 +399,7 @@ public async Task TestSqliteTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here } diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs index b8891025..5ca0cf9f 100644 --- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs +++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs @@ -387,10 +387,10 @@ public async Task TestSqliteTransaction() var connection = new Microsoft.Data.Sqlite.SqliteConnection(Environment.GetEnvironmentVariable(EndToEndCommon.SqliteConnectionStringEnv)); await connection.OpenAsync(); var transaction = connection.BeginTransaction(); - var sqlQueryWithTx = QuerySql.WithTransaction(transaction); - await sqlQueryWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); + var querySqlWithTx = QuerySql.WithTransaction(transaction); + await querySqlWithTx.CreateAuthor(new QuerySql.CreateAuthorArgs { Id = 1111, Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }); // The GetAuthor method in SqliteExampleGen returns QuerySql.GetAuthorRow? (nullable record struct/class) - var actualNull = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actualNull = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(actualNull == null, "there is author"); // This is correct for nullable types transaction.Commit(); var expected = new QuerySql.GetAuthorRow @@ -399,7 +399,7 @@ public async Task TestSqliteTransaction() Name = "Bojack Horseman", Bio = "Back in the 90s he was in a very famous TV show" }; - var actual = await this.QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); + var actual = await QuerySql.GetAuthor(new QuerySql.GetAuthorArgs { Name = "Bojack Horseman" }); Assert.That(SingularEquals(expected, actual)); // Apply placeholder here }