Link Search Menu Expand Document

DbRepository


This is the base class of all repository classes. It accepts the type of DbConnection as the generic type.

Use-Cases

You should implement this class if you wish to create a repository that is meant for processing all the database tables (and multiple entity models) together. This is a common design which we called a shared-repository.

Implementation

Let us say you have the following tables.

  • [dbo].[Customer]
  • [dbo].[Order]
  • [dbo].[Product]

And the following classes.

  • Customer
  • Order
  • Product

First, create a customized repository interface.

public interface INorthwithRepository
{
    // Create
    object CreateCustomer(Customer customer);
    object CreateOrder(Order order);
    object CreateProduct(Product product);
    // GetAll
    IEnumerable<Customer> GetCustomers();
    IEnumerable<Product> GetProducts();
    // GetOrders
    public IEnumerable<Order> GetCustomerOrders(int customerId);
}

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

public class NorthwindRepository : DbRepository<SqlConnection>, INorthwithRepository
{
    public NorthwindRepository(string connectionString)
        : base(connectionString)
    { }
}

Then, implement the needed interface methods.

Create

public object CreateCustomer(Customer customer)
{
    return Insert<Customer>(customer);
}

public object CreateOrder(Order order)
{
    return Insert<Order>(order);
}

public object CreateProduct(Product product)
{
    return Insert<Product>(product);
}

Get

public IEnumerable<Customer> GetCustomers()
{
    return QueryAll<Customer>();
}

public IEnumerable<Product> GetProducts()
{
    return QueryAll<Product>();
}

public IEnumerable<Order> GetCustomerOrders(int customerId)
{
    return Query<Order>(o => o.CustomerId == customerId);
}

/* More methods */

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 DbRepository reference implementation page for the detailed implementation.

Usability

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

using (var repository = new NorthwindRepository(settings.Value.ConnectionString)) // The settings must be DI(ed) (or,the repository itself must be DI(ed))
{
    var customers = repository.GetCustomers();
    customers
        .AsList()
        .ForEach(c =>
        {
            var orders = repository.GetCustomerOrders(c.Id);
            ProcessOrders(orders);
        });
}

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

Dependency Injection

Simply register the INorthwindRepository interface and the NorthwindRepository class in the service registration.

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

    // Registration
    services.AddTransient<INorthwindRepository, NorthwindRepository>();
}

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 instance-level connection persistency, simply pass the Connection Persistency value in the constructor.

public class NorthwindRepository : DbRepository<Customer, SqlConnection>
{
    public NorthwindRepository(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 NorthwindRepository : DbRepository<Customer, SqlConnection>
{
    public NorthwindRepository(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 NorthwindRepository : DbRepository<Customer, SqlConnection>
{
    public NorthwindRepository(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 NorthwindRepository : DbRepository<Customer, SqlConnection>
{
    public NorthwindRepository(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 NorthwindRepository : DbRepository<Customer, SqlConnection>
{
    public NorthwindRepository(string connectionString)
        : base(connectionString, new OptimizedSqlServerStatementBuilder)
    { }

    ...
}

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