Skip to content
Advertisement

Generic repository with Dapper

I’m trying to build a generic repository with Dapper. However, I have some difficulties to implement the CRUD-operations.

Here is some code from the repository:

 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 });
        }
    }
}

As you can see, my delete-method takes a TEntity as parameter which is a parameter of type class.

I call my Delete-method from my UserRepository like this:

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;
    }
}

The thing is that I can’t write entity.Id in my Delete-opration in my generic repository. I get a error. So how can I easily implement CRUD-operations like this?

Here is the error message:

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

Advertisement

Answer

Define an interface like so.

public interface ITypeWithId {
    int Id {get;}
}

And make sure your User type implements that interface.

Now apply it to your class as a generic constraint.

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

If you have types that are stored in the repository but DO Not have an Id property then make your delete type constraint specific to the method and not the class. This will allow you to still use the same repository type even with types that might key on something else like a string or a compound (multi) key.

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 });
    }
}
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement