Repositorio genérico con dapper

asp.net-mvc c# dapper sql

Pregunta

Estoy tratando de construir un repositorio genérico con dapper. Sin embargo, tengo algunas dificultades para implementar las operaciones CRUD.

Aquí hay un código del repositorio:

 public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    internal IDbConnection Connection
    {
        get
        {
            return new SqlConnection(ConfigurationManager.ConnectionStrings["SoundyDB"].ConnectionString);
        }
    }

    public GenericRepository(string tableName)
    {
        _tableName = tableName;
    }

    public void Delete(TEntity entity)
    {
        using (IDbConnection cn = Connection)
        {

            cn.Open();
            cn.Execute("DELETE FROM " + _tableName + " WHERE Id=@ID", new { ID = entity.Id });
        }
    }
}

Como puede ver, mi método de eliminación toma una TEntidad como parámetro, que es un parámetro de la clase de tipo.

Llamo a mi método Delete desde mi UserRepository de esta manera:

public class UserRepository : GenericRepository<User>, IUserRepository
{
    private readonly IConnectionFactory _connectionFactory;

    public UserRepository(IConnectionFactory connectionFactory) : base("User")
    {
        _connectionFactory = connectionFactory;
    }

    public async Task<User> Delete(User model)
    {
        var result = await Delete(model);
        return result;
    }
}

Lo que pasa es que no puedo escribir entity.Id en mi Delete-opration en mi repositorio genérico. Me sale un error Entonces, ¿cómo puedo implementar fácilmente operaciones CRUD como esta?

Aquí está el mensaje de error:

TEntity does not contain a definition of "Id" and no extension method "Id" accepting a argument of type "TEntity" could be found

Respuesta aceptada

Definir una interfaz como tal.

public interface ITypeWithId {
    int Id {get;}
}

Y asegúrese de que su tipo de User implemente esa interfaz.

Ahora aplícalo a tu clase como una restricción genérica.

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class, ITypeWithId

Si tiene tipos que están almacenados en el repositorio pero NO tienen una propiedad Id, haga que su restricción de tipo de eliminación sea específica del método y no de la clase. Esto le permitirá seguir utilizando el mismo tipo de repositorio incluso con tipos que puedan marcar otra cosa, como una cadena o una tecla compuesta (multi).

public void Delete<T>(T entity) where T : class, ITypeWithId
{
    using (IDbConnection cn = Connection)
    {

        cn.Open();
        cn.Execute("DELETE FROM " + _tableName + " WHERE Id=@ID", new { ID = entity.Id });
    }
}

Respuesta popular

Por favor no hagas esto! Su repositorio genérico agrega más confusión que valor. Es un código frágil (literales de cadena para _tableName, errores de conversión no válidos en el parámetro id) e introduce un agujero de seguridad enorme (inyección sql a través de _tableName). Si ha elegido Dapper, es porque quiere tener el control de su sql, por lo que no tiene sentido generar el sql que envía a Dapper.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué