Link Search Menu Expand Document

BaseRepository


This is the base class for all entity-based repository classes. It accepts two generic types — the model type and the connection type — and uses DbRepository as the underlying repository.

Use-Cases

Inherit this class to create a repository scoped to a single entity model/table.

Implementation

Given a table named [dbo].[Person] and a class named Person:

First, define a repository interface.

public interface IPersonRepository<TEntity, TPrimaryKey>
{
    int Create(Person person);
    Person GetById(int id);
    IEnumerable<Person> GetAll();
    int Update(Person person);
    int Merge(Person person);
    int Remove(Person person);
    int RemoveById(int id);
}

Then, create a class that inherits BaseRepository and implements the interface.

public class PersonRepository : BaseRepository<Person, SqlConnection>, IPersonRepository
{
    public PersonRepository(string connectionString)
        : base(connectionString)
    { }
}

Implement the interface methods.

Create

public int Create(Person person)
{
    return Insert<int>(person);
}

Get

public Person GetById(int id)
{
    return Query(id).FirstOrDefault();
}

public IEnumerable<Person> GetAll()
{
    return QueryAll();
}

Update

public int Update(Person person)
{
    return base.Update(person);
}

Merge

public int Merge(Person person)
{
    return base.Merge(person);
}

Remove

public int Remove(Person person)
{
    return Delete(person);
}

public int RemoveById(int id)
{
    return Delete(id);
}

Prepend the base keyword when your method name matches a base class method to avoid recursive calls. See the BaseRepository reference implementation for details.

Usability

Create a new instance of the repository to use it.

// The settings must be DI(ed) (or,the repository itself must be DI(ed))
using (var repository = new PersonRepository(settings.Value.ConnectionString))
{
    var person = repository.Get(10045);
}

The repository is disposable — wrap it in a using statement.

Dependency Injection

Register the interface and the implementation in the service collection.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    // Registration
    services.AddTransient<IPersonRepository, PersonRepository>();
}

Inject the interface, not the concrete class, to keep your design SOLID.

The CreateConnection Method

This method creates a new connection instance. If Connection Persistency is set to Instance, it returns the existing active connection.

Pass true to the force argument to always return a new connection.

using (var connection = CreateConnection(true))
{
    // Use the 'connection' here
}

Connection Persistency

This property controls connection lifetime within the repository. See Connection Persistency for details.

To enable instance-level persistency, pass ConnectionPersistency.Instance in the constructor.

public class PersonRepository : BaseRepository<Person, SqlConnection>, IPersonRepository
{
    public PersonRepository(string connectionString)
        : base(connectionString, ConnectionPersistency.Instance)
    { }

    ...
}

Command Timeout

This property sets the execution timeout for all operations. By default it is null, inheriting the ADO.NET default.

Pass a custom timeout value in the constructor.

public class PersonRepository : BaseRepository<Person, SqlConnection>, IPersonRepository
{
    public PersonRepository(string connectionString)
        : base(connectionString, 600)
    { }

    ...
}

Adding a Cache

This property enables second-layer caching for performance. By default, MemoryCache is used. Override by passing a custom ICache instance in the constructor.

public class MyCustomCache : ICache
{
    // Your cache implementation
}

Then pass it in the constructor.

public class PersonRepository : BaseRepository<Person, SqlConnection>, IPersonRepository
{
    public PersonRepository(string connectionString)
        : base(connectionString, new MyCustomCache())
    { }

    ...
}

See the JSON Cache reference implementation for file-based caching using JSON.

Adding a Trace

This property enables tracing and auditing of operation execution. Pass a custom ITrace instance in the constructor.

public class MyCustomTrace : ITrace
{
    // Your trace implementation
}

Then pass it in the constructor.

public class PersonRepository : BaseRepository<Person, SqlConnection>, IPersonRepository
{
    public PersonRepository(string connectionString)
        : base(connectionString, new MyCustomTrace())
    { }

    ...
}

See the Trace reference implementation for details.

SQL Builder

This property overrides the default SQL statement generator. Create a custom Statement Builder and pass an IStatementBuilder instance in the constructor.

public class OptimizedSqlServerStatementBuilder : IStatementBuilder
{
    // Your trace implementation
}

Then pass it in the constructor.

public class PersonRepository : BaseRepository<Person, SqlConnection>, IPersonRepository
{
    public PersonRepository(string connectionString)
        : base(connectionString, new OptimizedSqlServerStatementBuilder)
    { }

    ...
}

The constructor accepts any combination of the arguments described above.