Working with Dapper (Summary)

Dapper inspired me to develop a new "core architecture" for creating database contexts, "repositories" and using them in applications. In my design, the applications are data source agnostic, shielded by the repositories from the intricacies of the data layer. In practice, Dapper is used exclusively in the repository's CRUDS implementations.

The real big plus is Dapper's support for asynchronous (async-await) data access. Mendz.Data can't be complete without adding the asynchronous CRUDS interfaces.

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Mendz.Data
{
    public interface IDbDataCreatableAsync<T>
    {
        Task<T> CreateAsync(T model, dynamic expansion, 
            CancellationToken cancellationToken = default(CancellationToken));
    }

    public interface IDbDataReadableAsync<T>
    {
        Task<T> ReadAsync(T model, dynamic expansion, 
            CancellationToken cancellationToken = default(CancellationToken));
    }

    public interface IDbDataUpdatableAsync<T>
    {
        Task<T> UpdateAsync(T model, dynamic expansion, 
            CancellationToken cancellationToken = default(CancellationToken));
    }

    public interface IDbDataDeletableAsync<T>
    {
        Task<T> DeleteAsync(T model, dynamic expansion, 
            CancellationToken cancellationToken = default(CancellationToken));
    }

    public interface IDbDataSearchableAsync<T>
    {
        Task<IEnumerable<T>> SearchAsync<F, S>(
            F filter, S sort, dynamic expansion,
            int page, int pageSize, 
            CancellationToken cancellationToken = default(CancellationToken));
    }
}
This code defines the asynchronous versions of the CRUDS interfaces. The dynamic expansion parameter is still present. Note that there is no out parameter, which is not supported with async methods. The CancellationToken parameter is added to support cancellation of long running processes.

The asynchronous CRUDS interfaces complete the Mendz.Data library. It is important for implementers to use Dapper's asynchronous methods QueryAsync() and ExecuteAsync() methods in the implementations. It is strongly advised that the asynchronous CRUDS interfaces are NOT used with the synchronous methods of Dapper. Also, DO NOT use the asynchronous CRUDS interfaces to wrap synchronous CRUDS interface implementations for the sake of creating asynchronous versions.
  1. Working with Dapper (Part 1) - CRUDS
  2. Working with Dapper (Part 2) - ResultInfo and dynamic expansion
  3. Working with Dapper (Part 3) - CRUDS interfaces
  4. Working with Dapper (Part 4) - Example
The new "core architecture" delivers:
  • Stored procedures can store business logic and rules in one place.
  • Applications are data source agnostic.
  • The libraries can help the developer to be productive, flexible, creative and inventive.
And the good thing is that nothing fancy needed to be done. The new libraries are simple and quite easy to understand. By separating the CRUDS interfaces from DbRepositoryBase, developers can implement only what needs to be done. Instead of enforcing and restricting developers, the CRUDS interfaces are designed to guide, with the guidelines starting off by asking for the team's cooperation and discipline. The best thing? The team agrees and approves.

Comments