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
basekeyword 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
usingstatement.
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.