Solución:
Teníamos un proyecto que teníamos un repositorio genérico elegante, pero después de que el proyecto evolucionó, tenemos abandonado el repositorio genérico para utilizar el poder real de dapper.
Recomendaría usar Dapper como directo sin operaciones CRUD genéricas.
Para demostrar lo que teníamos, proporcionaré un código de muestra que no está listo para producción y le dará una idea para implementar su propio repositorio genérico.
public abstract class ConnectionBase : IDbConnection
protected ConnectionBase(IDbConnection connection)
Connection = connection;
protected IDbConnection Connection get; private set;
// Verbose but necessary implementation of IDbConnection:
#region "IDbConnection implementation"
public string ConnectionString
get
return Connection.ConnectionString;
set
Connection.ConnectionString = value;
public int ConnectionTimeout
get
return Connection.ConnectionTimeout;
public string Database
get
return Connection.Database;
public ConnectionState State
get
return Connection.State;
public IDbTransaction BeginTransaction()
return Connection.BeginTransaction();
public void Close()
Connection.Close();
public IDbCommand CreateCommand()
return Connection.CreateCommand();
public void Dispose()
Connection.Dispose();
public void Open()
Connection.Open();
#endregion
Repositorio genérico
public abstract class GenericRepository : IRepository where T : class //EntityBase, IAggregateRoot
private readonly string _tableName;
internal IDbConnection Connection
get
return new SqlConnection(ConfigurationManager.ConnectionStrings["SmsQuizConnection"].ConnectionString);
public GenericRepository(string tableName)
_tableName = tableName;
internal virtual dynamic Mapping(T item)
return item;
public virtual void Add(T item)
using (IDbConnection cn = Connection)
var parameters = (object)Mapping(item);
cn.Open();
item.ID = cn.Insert(_tableName, parameters);
public virtual void Update(T item)
using (IDbConnection cn = Connection)
var parameters = (object)Mapping(item);
cn.Open();
cn.Update(_tableName, parameters);
public virtual void Remove(T item)
using (IDbConnection cn = Connection)
cn.Open();
cn.Execute("DELETE FROM " + _tableName + " WHERE [email protected]", new ID = item.ID );
public virtual T FindByID(Guid id)
T item = default(T);
using (IDbConnection cn = Connection)
cn.Open();
item = cn.Query("SELECT * FROM " + _tableName + " WHERE [email protected]", new ID = id ).SingleOrDefault();
return item;
public virtual IEnumerable FindAll()
IEnumerable items = null;
using (IDbConnection cn = Connection)
cn.Open();
items = cn.Query("SELECT * FROM " + _tableName);
return items;
Los ejemplos de @PathumLakshan solicitan los comentarios. Los ejemplos proporcionados se escriben de forma asincrónica, pero la fuente se puede implementar de forma síncrona. De todos modos, es solo una ilustración de cómo puede administrar la infraestructura con Dapper. Clase Db
proporciona algunos métodos genéricos para obtener datos y ejecutar consultas SQL. Por ejemplo, puede usar sobrecarga Get
para consultas básicas, o tome Get
para usar deja decir QueryMultiple
. Clase Repository
muestra, cómo puede verse el repositorio básico para la entidad Entity
.
Db clase:
public class Db : IDb
{
private readonly Func _dbConnectionFactory;
public Db(Func dbConnectionFactory)
_dbConnectionFactory = dbConnectionFactory ?? throw new ArgumentNullException(nameof(dbConnectionFactory));
public async Task CommandAsync(Func> command)
using (var connection = _dbConnectionFactory.Invoke())
await connection.OpenAsync();
using (var transaction = connection.BeginTransaction())
try
var result = await command(connection, transaction, Constants.CommandTimeout);
transaction.Commit();
return result;
catch (Exception ex)
transaction.Rollback();
Logger.Instance.Error(ex);
throw;
public async Task GetAsync(Func> command)
return await CommandAsync(command);
public async Task> SelectAsync(Func>> command)
return await CommandAsync(command);
public async Task ExecuteAsync(string sql, object parameters)
await CommandAsync(async (conn, trn, timeout) =>
await conn.ExecuteAsync(sql, parameters, trn, timeout);
return 1;
);
public async Task GetAsync(string sql, object parameters)
return await CommandAsync(async (conn, trn, timeout) =>
T result = await conn.QuerySingleAsync(sql, parameters, trn, timeout);
return result;
);
public async Task> SelectAsync(string sql, object parameters)
return await CommandAsync>(async (conn, trn, timeout) =>
var result = (await conn.QueryAsync(sql, parameters, trn, timeout)).ToList();
return result;
);
Repositorio clase:
public class Repository : IRepository
protected readonly IDb _db;
public Repository(IDb db)
_db = db ?? throw new
ArgumentException(nameof(db));
public async Task Add(Entity entity)
await _db.ExecuteAsync("INSERT INTO ... VALUES...", entity);
public async Task Update(Entity entity)
await _db.ExecuteAsync("UPDATE ... SET ...", entity);
public async Task Remove(Entity entity)
await _db.ExecuteAsync("DELETE FROM ... WHERE ...", entity);
public async Task FindByID(int id)
return await _db.GetAsync("SELECT ... FROM ... WHERE Id = @id", new id );
public async Task> FindAll()
return await _db.SelectAsync("SELECT ... FROM ... ", new );
Db
se puede ampliar con otro método genérico, por ejemplo, ExecuteScalar
, que necesitaría en sus repositorios. Espero eso ayude.
Comentarios y calificaciones del post
Puedes asentar nuestra publicación exponiendo un comentario y dejando una valoración te damos las gracias.