I have an ASP.NET Core 3.1 Web API project which is leveraging Dapper for database operations.
I have following method in the ISqlDapperClient.cs
ISqlDapperClient.cs
public interface ISqlDapperClient
{
Task<IReadOnlyList<T>> QueryReadOnlyListAsync<T>(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);
}
SqlDapperClient.cs
public class SqlDapperClient : ISqlDapperClient
{
private readonly ILogger<SqlDapperClient> _logger;
private readonly IAsyncPolicy _resiliencyPolicy;
private readonly IConfiguration _configuration;
private readonly string _dbConnection;
private readonly IDBAuthTokenService _dbTokenService;
private readonly IDbConnection _connection;
public SqlDapperClient(ILogger<SqlDapperClient> logger, IConfiguration configuration, IDBAuthTokenService dbTokenService)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_resiliencyPolicy = SqlResiliencyPolicy.GetSqlResiliencyPolicy(); //resiliencyPolicy ?? throw new ArgumentNullException(nameof(resiliencyPolicy));
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
// Read the connectionstring
_dbConnection = _configuration[C.VaultKeys.DataDBConnString] ?? _configuration[C.AppKeys.LocalDataDBConn];
_dbTokenService = dbTokenService ?? throw new ArgumentNullException(nameof(dbTokenService));
_connection = OpenConnectionWithRetryAsync().Result;
}
/// <summary>
/// Method that returns IDbConnection to connect with database
/// </summary>
/// <returns>IDbConnection</returns>
private async Task<IDbConnection> OpenConnectionWithRetryAsync()
{
var conn = new SqlConnection(_dbConnection)
{AccessToken = await _dbTokenService.GetTokenAsync()};
await conn.OpenAsync();
return conn;
}
public Task<IReadOnlyList<T>> QueryReadOnlyListAsync<T>(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) => ExecuteWithResiliency((s, p, c) => c.QueryAsync<T>(s, p, transaction, commandTimeout, commandType), sql, param);
private async Task<T> ExecuteWithResiliency<T>(Func<string, object, SqlConnection, Task<T>> connectionFunc, string sql, object param = null, [CallerMemberName] string operation = "")
{
return await _resiliencyPolicy.ExecuteAsync(ctx => connectionFunc(sql, param, (SqlConnection)_connection), ContextHelper.NewContext((SqlConnection)_connection, _logger, sql, param, operation));
}
}
I am getting compile time error in the method : QueryReadOnlyListAsync
Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<T>>' to 'System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<T>>'
Can anyone help me here by providing their guidance?
CodePudding user response:
QueryReadOnlyListAsync
calls the Dapper extension method QueryAsync
, which returns a Task<IEnumerable<T>>
. IEnumerable
doesn't implement IReadOnlyList
. You can't return Task<IEnumerable>
if the method's return type is Task<IReadOnlyList>
. You need to convert the IEnumerable
into a collection that implements IReadOnlyList
, such as a regular List
:
//Make method async so you can await the Task returned by ExecuteWithResiliency
public async Task<IReadOnlyList<T>> QueryReadOnlyListAsync<T>(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{
//Converting using .ToList() for simplicity. Use whatever type suits your use-case best.
return (await ExecuteWithResiliency((s, p, c) => c.QueryAsync<T>(s, p, transaction, commandTimeout, commandType), sql, param)).ToList();
}
private async Task<T> ExecuteWithResiliency<T>(Func<string, object, SqlConnection, Task<T>> connectionFunc, string sql, object param = null, [CallerMemberName] string operation = "")
{
return await _resiliencyPolicy.ExecuteAsync(ctx => connectionFunc(sql, param, (SqlConnection)_connection), ContextHelper.NewContext((SqlConnection)_connection, _logger, sql, param, operation));
}