Dapper extensions for plinth database framework for PosgreSQL
$ dotnet add package Plinth.Database.Dapper.PgSqlExtension for Plinth.Database.PgSql to support Dapper for object mapping
Extends Plinth.Database.PgSql to allow using Dapper to map objects to input parameters and result sets to output objects instead of manual mapping.
No additional configuration changes are required to support Dapper. The only necessary action is to install this package.
:point_right: To access Dapper methods, call the .Dapper() extension method on ISqlConnection
Below is an example controller that creates a transaction, executes a stored procedure, and returns the result.
[Route("api/[controller]")]
[ApiController]
public class MyThingController : Controller
{
private readonly ISqlTransactionProvider _txnProvider;
public MyThingController(ISqlTransactionProvider _txnProvider)
{
_txnProvider = txnProvider;
}
[HttpGet]
[Route("{thingId}")]
[ProducesResponseType(200)]
public async Task<ActionResult<MyThing>> GetMyThing(Guid thingId, CancellationToken ct)
{
var myThing = await _txnProvider.ExecuteTxnAsync(connection =>
{
return await connection.Dapper().ExecuteQueryProcOneAsync<MyThing>(
"fn_get_mything_by_id",
new { i_thing_id = thingId }).Value;
}, ct);
if (myThing is null)
throw new LogicalNotFoundException($"MyThing {thingId} was not found");
return Ok(myThing);
}
}
To execute a stored procedure that does not return a result set, use one of these three options. Typically used with DML procedures that insert/update/delete.
:point_right: All forms accepts CancellationToken
ExecuteProcAsync(string procName, object? param, CancellationToken cancellationToken)
ExecuteProcAsync(string procName, int expectedRows, object? param, CancellationToken cancellationToken)
expectedRowsExecuteProcUncheckedAsync(string procName, object? param, CancellationToken cancellationToken)
To execute a stored procedure returns a result set, use one of these three options. Typically used with SELECT queries.
:point_right: All forms accept a CancellationToken
ExecuteQueryProcListAsync<T>(string procName, object? param, CancellationToken cancellationToken)
IEnumerable<T> of <T> mapped by Dapper.IEnumerable<T> that may be empty.ExecuteQueryProcOneAsync<T>(string procName, object? param, CancellationToken cancellationToken)
Some stored procedures can actually return multiple result sets in a single call.
To execute and process each result set, use this method:
ExecuteQueryProcMultiResultSetAsync(string procName, Func<IDapperMultiResultSetAsync, Task> readerAction, object? param, CancellationToken cancellationToken)
Example
await c.Dapper().ExecuteQueryProcMultiResultSetAsync(
"fn_get_multiple_results",
async (mrs) =>
{
await processSet1(mrs);
await processSet2(mrs);
await processSet3(mrs);
},
new { i_int1 = 10 });
public void processSet1(IDapperMultiResultSetAsync mrs)
{
var items = (await mrs.GetListAsync<MyThing1>()).ToList();
// do something with items
}
IDapperMutliResultSetAsync has these methods for processing each result set
.GetListAsync<T>(CancellationToken cancellationToken)
IEnumerable<T> of <T> mapped by Dapper.IEnumerable<T> that may be empty.GetOneAsync<T>(CancellationToken cancellationToken)
Normal transactions as shown above only allow for executing stored procedures. There are times and cases where executing a raw SQL statement is required. To do so, use ExecuteRawTxnAsync as shown in the below example:
var myThing = await _txnProvider.ExecuteRawTxnAsync(connection =>
{
return await connection.Dapper().ExecuteRawQueryOneAsync<MyThing>(
"SELECT i_field1, dt_field2 FROM my_things WHERE i_thing_id = @i_thing_id",
new { i_thing_id = thingId }).Value;
}, ct);
The methods are analogues of the methods in sections 3, 4 and 5.
ExecuteRawAsync for DMLExecuteRawQueryListAsync for queries that return a list of resultsExecuteRawQueryOneAsync for queries that return a single resultExecuteRawQueryMultiResultSetAsync for queries that return multiple result sets