Link Search Menu Expand Document

BaseRepository


This is the base class of all entity-based repository classes. It accepts 2 generic types, the model type and the connection type. It uses the DbRepository as the underlying controlling repository.

Use-Cases

You should inherit this class if you wish to create a repository that is meant for processing a single entity model/table only.

Implementation

Let us say you have a table named [dbo].[Person] and a class named Person.

First, create a customized entity-based 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);
}

Secondly, create a class that inherits from BaseRepository class. In this class, implement the newly created interface-repository above.

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

Then, implement the needed 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);
}

Beware of the recurring calls. Ensure to prepend the base keyword if your method name is with the same signature as with the base. Please visit our BaseRepository reference implementation page for the detailed implementation.

Usability

Simply create a new instance of the class to use the repository.

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

A respository is disposable, so please do not forget to wrap it with using keyword.

Dependency Injection

Simply register the IPersonRepository interface and the PersonRepository class in the service registration.

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

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

Do not use the repository class directly as the injected object to make your design more SOLID (adhering the single-responsibility concepts).

The CreateConnection Method

This method is used to create a new instance of connection object. If the value of Connection Persistency enumeration is Instance, then this method returns the existing active connection.

To always force returning the new instance of connection object, simply pass true in the force argument.

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

Connection Persistency

This property enables your repository to manage the persistency of your connection within the lifespan of the repository. Please have a look at the Connection Persistency enumeration to see more details.

To enable an instanced-level connection persistency, simply pass the Connection Persistency value in the constructor.

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

    ...
}

Command Timeout

This property is used as the execution timeout of every operation. By default it is null; defaultly using the ADO.NET execution timeout.

To enable your customized timeout, simply pass it on the constructor.

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

    ...
}

Adding a Cache

This property allows the repository to enable the 2nd-layer cache for the purpose of performance. By default, the caching is enabled with the use of MemoryCache. You can override the caching by passing the instance of ICache-based class in the constructor.

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

Then, pass it on the constructor.

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

    ...
}

Please visit our JSON Cache reference implementation page for the detailed implementation about file-based caching using JSON.

Adding a Trace

This property allows you as a developer to trace and audit the execution of any operation in the repository. To enable the trace, you have to pass the instance of ITrace-based class in the constructor.

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

Then, pass it on the constructor.

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

    ...
}

Please visit our Trace reference implementation page for the detailed implementation.

SQL Builder

This property allows you to override the default SQL statement generator of the library. To override, you have to create your custom Statement Builder and pass the instance of IStatementBuilder-based class in the constructor.

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

Then, pass it on the constructor.

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

    ...
}

The constructor of this class accepts all the possible combinations of the argument mentioned above.