diff --git a/EnvelopeGenerator.Application/Contracts/SQLExecutor/ISQLExecutor.cs b/EnvelopeGenerator.Application/Contracts/SQLExecutor/ISQLExecutor.cs
index 245657e9..5ff732e4 100644
--- a/EnvelopeGenerator.Application/Contracts/SQLExecutor/ISQLExecutor.cs
+++ b/EnvelopeGenerator.Application/Contracts/SQLExecutor/ISQLExecutor.cs
@@ -1,41 +1,27 @@
namespace EnvelopeGenerator.Application.Contracts.SQLExecutor;
///
-/// Defines methods for executing raw SQL queries and mapping the results to objects.
+/// Defines methods for executing raw SQL queries or custom SQL query classes and returning query executors for further operations.
+/// Provides abstraction for raw SQL execution as well as mapping the results to objects.
///
/// The entity type to which the SQL query results will be mapped.
public interface ISQLExecutor
{
///
- /// Executes a raw SQL query and returns the first result or null if no result is found.
+ /// Executes a raw SQL query and returns an for further querying operations on the result.
///
/// The raw SQL query to execute.
- /// Optional cancellation token.
+ /// Optional cancellation token for the operation.
/// Optional parameters for the SQL query.
- /// The first result, or null if none found.
- Task ExecuteFirstAsync(string sql, CancellationToken cancellation = default, params object[] parameters);
+ /// An instance for further query operations on the result.
+ IQueryExecutor Execute(string sql, CancellationToken cancellation = default, params object[] parameters);
///
- /// Executes a raw SQL query and expects a single result, or null if no result is found.
+ /// Executes a custom SQL query defined by a class that implements and returns an for further querying operations on the result.
///
- /// The raw SQL query to execute.
- /// Optional cancellation token.
+ /// The type of the custom SQL query class implementing .
+ /// Optional cancellation token for the operation.
/// Optional parameters for the SQL query.
- /// The single result, or null if none found.
- Task ExecuteSingleAsync(string sql, CancellationToken cancellation = default, params object[] parameters);
-
- ///
- /// Executes a raw SQL query and returns all results as a collection of .
- ///
- /// The raw SQL query to execute.
- /// Optional cancellation token.
- /// Optional parameters for the SQL query.
- /// An containing all matching results.
- Task> ExecuteAllAsync(string sql, CancellationToken cancellation = default, params object[] parameters);
-
- Task ExecuteFirstAsync(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL;
-
- Task ExecuteSingleAsync(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL;
-
- Task> ExecuteAllAsync(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL;
+ /// An instance for further query operations on the result.
+ IQueryExecutor Execute(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL;
}
diff --git a/EnvelopeGenerator.Infrastructure/QueryExecutor.cs b/EnvelopeGenerator.Infrastructure/QueryExecutor.cs
index dcf148a2..72553370 100644
--- a/EnvelopeGenerator.Infrastructure/QueryExecutor.cs
+++ b/EnvelopeGenerator.Infrastructure/QueryExecutor.cs
@@ -1,34 +1,42 @@
-using EnvelopeGenerator.Application.Contracts.SQLExecutor;
+using AngleSharp.Dom;
+using EnvelopeGenerator.Application.Contracts.SQLExecutor;
using Microsoft.EntityFrameworkCore;
namespace EnvelopeGenerator.Infrastructure;
-public record QueryExecutor(IQueryable Queryable) : IQueryExecutor
+public sealed record QueryExecutor : IQueryExecutor
{
- public TEntity First() => Queryable.First();
+ private readonly IQueryable _query;
- public Task FirstAsync() => Queryable.FirstAsync();
+ internal QueryExecutor(IQueryable queryable)
+ {
+ _query = queryable;
+ }
- public TEntity? FirstOrDefault() => Queryable.FirstOrDefault();
+ public TEntity First() => _query.First();
+
+ public Task FirstAsync() => _query.FirstAsync();
+
+ public TEntity? FirstOrDefault() => _query.FirstOrDefault();
- public Task FirstOrDefaultAsync() => Queryable.FirstOrDefaultAsync();
+ public Task FirstOrDefaultAsync() => _query.FirstOrDefaultAsync();
- public TEntity Single() => Queryable.Single();
+ public TEntity Single() => _query.Single();
- public Task SingleAsync() => Queryable.SingleAsync();
+ public Task SingleAsync() => _query.SingleAsync();
- public TEntity? SingleOrDefault() => Queryable.SingleOrDefault();
+ public TEntity? SingleOrDefault() => _query.SingleOrDefault();
- public Task SingleOrDefaultAsync() => Queryable.SingleOrDefaultAsync();
+ public Task SingleOrDefaultAsync() => _query.SingleOrDefaultAsync();
- public IEnumerable ToList() => Queryable.ToList();
+ public IEnumerable ToList() => _query.ToList();
- public async Task> ToListAsync() => await Queryable.ToListAsync();
-}
+ public async Task> ToListAsync() => await _query.ToListAsync();
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Infrastructure/QueryExecutorExtension.cs b/EnvelopeGenerator.Infrastructure/QueryExecutorExtension.cs
new file mode 100644
index 00000000..dbc0aa18
--- /dev/null
+++ b/EnvelopeGenerator.Infrastructure/QueryExecutorExtension.cs
@@ -0,0 +1,9 @@
+namespace EnvelopeGenerator.Infrastructure;
+
+public static class QueryExecutorExtension
+{
+ public static QueryExecutor ToExecutor(this IQueryable queryable) where TEntity : class
+ {
+ return new QueryExecutor(queryable);
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Infrastructure/SQLExecutor.cs b/EnvelopeGenerator.Infrastructure/SQLExecutor.cs
index 050beb28..2c25840a 100644
--- a/EnvelopeGenerator.Infrastructure/SQLExecutor.cs
+++ b/EnvelopeGenerator.Infrastructure/SQLExecutor.cs
@@ -10,44 +10,21 @@ public sealed class SQLExecutor : ISQLExecutor where T : class
private readonly IServiceProvider _provider;
- public SQLExecutor(EGDbContext context)
+ public SQLExecutor(EGDbContext context, IServiceProvider provider)
{
_context = context;
+ _provider = provider;
}
- public async Task ExecuteFirstAsync(string sql, CancellationToken cancellation = default, params object[] parameters)
- => await _context
- .Set()
- .FromSqlRaw(sql, parameters)
- .FirstOrDefaultAsync(cancellation);
+ public IQueryExecutor Execute(string sql, CancellationToken cancellation = default, params object[] parameters)
+ => _context
+ .Set()
+ .FromSqlRaw(sql, parameters)
+ .ToExecutor();
- public async Task ExecuteSingleAsync(string sql, CancellationToken cancellation = default, params object[] parameters)
- => await _context
- .Set()
- .FromSqlRaw(sql, parameters)
- .SingleOrDefaultAsync(cancellation);
-
- public async Task> ExecuteAllAsync(string sql, CancellationToken cancellation = default, params object[] parameters)
- => await _context
- .Set()
- .FromSqlRaw(sql, parameters)
- .ToListAsync(cancellation);
-
- public Task ExecuteFirstAsync(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL
+ public IQueryExecutor Execute(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL
{
var sql = _provider.GetRequiredService();
- return ExecuteFirstAsync(sql.Raw);
- }
-
- public Task ExecuteSingleAsync(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL
- {
- var sql = _provider.GetRequiredService();
- return ExecuteSingleAsync(sql.Raw);
- }
-
- public Task> ExecuteAllAsync(CancellationToken cancellation = default, params object[] parameters) where TSQL : ISQL
- {
- var sql = _provider.GetRequiredService();
- return ExecuteAllAsync(sql.Raw);
+ return Execute(sql.Raw);
}
}