Skip to content

Commit

Permalink
#343 CancellationToken Support for PosgreSQL DbHelper/Cache
Browse files Browse the repository at this point in the history
  • Loading branch information
mikependon committed Oct 2, 2020
1 parent 7b9ed68 commit eda8e5b
Showing 1 changed file with 39 additions and 16 deletions.
55 changes: 39 additions & 16 deletions RepoDb.PostgreSql/RepoDb.PostgreSql/DbHelpers/PostgreSqlDbHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -45,9 +46,9 @@ public PostgreSqlDbHelper(IResolver<string, Type> dbTypeResolver)
#region Helpers

/// <summary>
/// Returns the command text that is being used to extract schema definitions.
///
/// </summary>
/// <returns>The command text.</returns>
/// <returns></returns>
private string GetCommandText()
{
return @"
Expand Down Expand Up @@ -76,11 +77,11 @@ JOIN information_schema.constraint_column_usage AS CCU USING (constraint_schema,
}

/// <summary>
/// Converts the <see cref="IDataReader"/> object into <see cref="DbField"/> object.
///
/// </summary>
/// <param name="reader">The instance of <see cref="IDataReader"/> object.</param>
/// <returns>The instance of converted <see cref="DbField"/> object.</returns>
private DbField ReaderToDbField(IDataReader reader)
/// <param name="reader"></param>
/// <returns></returns>
private DbField ReaderToDbField(DbDataReader reader)
{
return new DbField(reader.GetString(0),
reader.IsDBNull(1) ? false : reader.GetBoolean(1),
Expand All @@ -93,6 +94,26 @@ private DbField ReaderToDbField(IDataReader reader)
reader.IsDBNull(4) ? "text" : reader.GetString(4));
}

/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<DbField> ReaderToDbFieldAsync(DbDataReader reader,
CancellationToken cancellationToken = default)
{
return new DbField(await reader.GetFieldValueAsync<string>(0, cancellationToken),
await reader.IsDBNullAsync(1, cancellationToken) ? false : await reader.GetFieldValueAsync<bool>(1, cancellationToken),
await reader.IsDBNullAsync(2, cancellationToken) ? false : await reader.GetFieldValueAsync<bool>(2, cancellationToken),
await reader.IsDBNullAsync(3, cancellationToken) ? false : await reader.GetFieldValueAsync<bool>(3, cancellationToken),
await reader.IsDBNullAsync(4, cancellationToken) ? DbTypeResolver.Resolve("text") : DbTypeResolver.Resolve(await reader.GetFieldValueAsync<string>(4, cancellationToken)),
null,
null,
null,
await reader.IsDBNullAsync(4) ? "text" : reader.GetString(4));
}

#endregion

#region Methods
Expand All @@ -119,7 +140,7 @@ public IEnumerable<DbField> GetFields(IDbConnection connection,
};

// Iterate and extract
using (var reader = connection.ExecuteReader(commandText, param, transaction: transaction))
using (var reader = (DbDataReader)connection.ExecuteReader(commandText, param, transaction: transaction))
{
var dbFields = new List<DbField>();

Expand All @@ -140,15 +161,13 @@ public IEnumerable<DbField> GetFields(IDbConnection connection,
/// <param name="connection">The instance of the connection object.</param>
/// <param name="tableName">The name of the target table.</param>
/// <param name="transaction">The transaction object that is currently in used.</param>
/// <param name="cancellationToken"> A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> object to be used during the asynchronous operation.</param>
/// <returns>A list of <see cref="DbField"/> of the target table.</returns>
public async Task<IEnumerable<DbField>> GetFieldsAsync(IDbConnection connection,
string tableName,
IDbTransaction transaction = null,
CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();

// Variables
var commandText = GetCommandText();
var param = new
Expand All @@ -158,14 +177,15 @@ public async Task<IEnumerable<DbField>> GetFieldsAsync(IDbConnection connection,
};

// Iterate and extract
using (var reader = await connection.ExecuteReaderAsync(commandText, param, transaction: transaction))
using (var reader = (DbDataReader)await connection.ExecuteReaderAsync(commandText, param, transaction: transaction,
cancellationToken: cancellationToken))
{
var dbFields = new List<DbField>();

// Iterate the list of the fields
while (reader.Read())
while (await reader.ReadAsync(cancellationToken))
{
dbFields.Add(ReaderToDbField(reader));
dbFields.Add(await ReaderToDbFieldAsync(reader));
}

// Return the list of fields
Expand All @@ -187,20 +207,23 @@ public object GetScopeIdentity(IDbConnection connection,
IDbTransaction transaction = null)
{
// TODO: May fail with trigger?
return connection.ExecuteScalar("SELECT lastval();");
return connection.ExecuteScalar("SELECT lastval();", transaction: transaction);
}

/// <summary>
/// Gets the newly generated identity from the database in an asynchronous way.
/// </summary>
/// <param name="connection">The instance of the connection object.</param>
/// <param name="transaction">The transaction object that is currently in used.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> object to be used during the asynchronous operation.</param>
/// <returns>The newly generated identity from the database.</returns>
public async Task<object> GetScopeIdentityAsync(IDbConnection connection,
IDbTransaction transaction = null)
IDbTransaction transaction = null,
CancellationToken cancellationToken = default)
{
// TODO: May fail with trigger?
return await connection.ExecuteScalarAsync("SELECT lastval();");
return await connection.ExecuteScalarAsync("SELECT lastval();", transaction: transaction,
cancellationToken: cancellationToken);
}

#endregion
Expand Down

0 comments on commit eda8e5b

Please sign in to comment.