Repository of trainers This is my first asp.net core web api and i did followed the Repository pattern but i don't know whether this approach is good practice.

public class TrainerRepo : IRepoTrainer
{
    private readonly IConfiguration _config;

    public TrainerRepo(IConfiguration config)
    {
        _config = config;
    }

    public IDbConnection dbConnection
    {
        get
        {
            return new SqlConnection(_config.GetConnectionString("MyConnString"));
        }
    }

    public List&lt;Trainer&gt; GetTrainers()
    {
        string sql = "select trainer_id,trainer_name from trainer";
        using(IDbConnection conn = dbConnection)
        {
            conn.Open();
            var res = conn.Query&lt;Trainer&gt;(sql).ToList&lt;Trainer&gt;();
            conn.Close();
            return res;
        }

    }

    public int NewTrainer(Trainer trainer)
    {
        string sql = "insert into trainer ( trainer_name) values ( @name)";
        using(IDbConnection conn = dbConnection)
        {
            conn.Open();
            var res = conn.Execute(sql, param: new
            {
                //id = trainer.trainer_id,
                name = trainer.trainer_name
            });
            conn.Close();
            return res;
        }
    }

    public async Task&lt;int&gt; updateTrainer(Trainer trainer)
    {
        string sql = "update trainer set trainer_name = @tname where trainer_id = @tid";
        using(IDbConnection conn = dbConnection)
        {
            conn.Open();
            var res = await conn.ExecuteAsync(sql, param: new { tname = trainer.trainer_name, tid = trainer.trainer_id });
            conn.Close();
            return res;
        }
    }

    public int deleteTrainer(int id)
    {
        string sql = "delete from trainer where trainer_id=@trainerId";
        using(IDbConnection conn = dbConnection)
        {
            conn.Open();
            var res =  conn.Execute(sql, param: new { trainerId = id });
            conn.Close();
            return res;
        }
    }

}


IRepoTrainer interface

public interface IRepoTrainer
{
    List&lt;Trainer&gt; GetTrainers();
    int NewTrainer(Trainer trainer);
    Task&lt;int&gt; updateTrainer(Trainer trainer);
    int deleteTrainer(int id);
}


my problem is that reuse of following code block, is it good practice ?

 using(IDbConnection conn = dbConnection)
   {
    conn.Open();
    //
    conn.Close();
    return res;
   }
It has been suggested in docs to not pass IConfiguration around for injection. Try creating a IConnectionFactory or just have a connection injected directly into the repo

Something like

public interface IDbConnectionFactory {
   IDbConnection CreateConnection();
}


and its implementation for your class would look something like this

public class SqlConnectionFactory : IDbConnectionFactory {
    private readonly string dbConnectionString;

    public SqlConnectionFactory(string dbConnectionString) {
        this.dbConnectionString = dbConnectionString;
    }

    public IDbConnection CreateConnection() {
        return new SqlConnection(this.dbConnectionString);
    }
}


it would be registered in startup

var connectionString = Configuration.GetConnectionString("MyConnString");
services.AddScoped&lt;IDbConnectionFactory, SqlConnectionFactory&gt;(_ =&gt; new SqlConnectionFactory(connectionString));

//...


and injected

public class TrainerRepo : IRepoTrainer {
    private readonly IDbConnectionFactory factory;

    public TrainerRepo(IDbConnectionFactory factory) {
        this.factory = factory;
    }

    public List&lt;Trainer&gt; GetTrainers() {
        string sql = "select trainer_id,trainer_name from trainer";
        using(IDbConnection connection = factory.CreateConnection()) {
            connection.Open();
            var res = connection.Query&lt;Trainer&gt;(sql).ToList&lt;Trainer&gt;();
            connection.Close();
            return res;
        }
    }

    //...


The repeated code can also be generalized

T Invoke&lt;T&gt;(Func&lt;IDbConnection, T&gt; func) {
    using(IDbConnection connection = factory.CreateConnection()) {
        connection.Open();
        var res = func(connection);
        connection.Close();
        return res;
    }
}

async Task&lt;TResult&gt; InvokeAsync&lt;TResult&gt;(Func&lt;IDbConnection, Task&lt;TResult&gt;&gt; func) {
    using(IDbConnection connection = factory.CreateConnection()) {
        connection.Open();
        var res = await func(connection);
        connection.Close();
        return res;
    }
}


Which changes the previous examples to

public List&lt;Trainer&gt; GetTrainers() {
    string sql = "select trainer_id,trainer_name from trainer";
    return Invoke(connection =&gt; connection.Query&lt;Trainer&gt;(sql).ToList&lt;Trainer&gt;());
}


public Task&lt;int&gt; updateTrainer(Trainer trainer) {
    string sql = "update trainer set trainer_name = @tname where trainer_id = @tid";
    return  InvokeAsync(connection =&gt; connection.ExecuteAsync(sql, param: new { tname = trainer.trainer_name, tid = trainer.trainer_id }));
}