Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion CodeGenerator/Generators/QueriesGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,19 @@ public class {{className}}
{
{{dbDriver.GetConstructorStatements().JoinByNewLine()}}
}
private string {{Variable.ConnectionString.AsPropertyName()}} { get; }

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; }
}
""")!;
return classDeclaration.AddMembers(classMembers.ToArray());
Expand Down
12 changes: 12 additions & 0 deletions Drivers/DbDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public abstract class DbDriver

public string DefaultSchema { get; }

public abstract string TransactionClassName { get; }

public Dictionary<string, Dictionary<string, Table>> Tables { get; }

public Dictionary<string, Dictionary<string, Plugin.Enum>> Enums { get; }
Expand Down Expand Up @@ -118,6 +120,16 @@ public virtual string[] GetConstructorStatements()
.ToArray();
}

public virtual string[] GetTransactionConstructorStatements()
{
return new List<string>
{
$"this.{Variable.Transaction.AsPropertyName()} = {Variable.Transaction.AsVarName()};"
}
.AppendIf("Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;", Options.UseDapper)
.ToArray();
}

public virtual MemberDeclarationSyntax[] GetMemberDeclarationsForUtils()
{
return [];
Expand Down
121 changes: 88 additions & 33 deletions Drivers/Generators/ExecDeclareGen.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Plugin;
using System.Linq;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace SqlcGenCsharp.Drivers.Generators;
Expand All @@ -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)
Comment thread
SockworkOrange marked this conversation as resolved.
{
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();
}
""";
}
}
119 changes: 85 additions & 34 deletions Drivers/Generators/ExecLastIdDeclareGen.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Plugin;
using System.Linq;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace SqlcGenCsharp.Drivers.Generators;
Expand All @@ -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}}
}
""";
}
}
Loading