Trackable Entities – Now with Repository and Unit of Work

When I released v1.0 of my Trackable Entities Framework, it came with a lot of developer goodness: NuGet packages, Visual Studio project templates, a VSIX installer available from Visual Studio’s Extensions Gallery, Getting Started guides and a screencast. From the start I built in support for both ASP.NET Web API and Windows Communication Foundation (WCF) using either Visual Studio 2012 or 2013.

With inquires on the project discussion forum, and some prompting by my friend Long Le, who authored the Generic Unit of Work and Repository Framework, I decided to add support to my framework for using Repository and Unit of Work design patterns.  I’ve used these patterns for a number of years with an approach to application design called the Onion Architecture (first proposed by Jeffery Palermo).  The idea behind it is to use dependency injection with interfaces to loosely couple your service applications to infrastructure concerns, such as data access and logging, and in so doing, future-proof your application against technology obsolescence.

While we architects love design patterns and loose coupling, there is a price to pay, which is increased complexity and more moving parts.  With this also comes a temptation to do too much for the developer in order to reduce the level of complexity.  The result is a delicate balancing act, with trade-offs between ease of use and architectural soundness.  In particular, generic repositories that expose IQueryable for creating composable queries have been criticized as a lazy anti-pattern, because they can obscure the contract which a repository should represent between the domain objects and a data store.

To be fair, Long is refactoring his framework to alleviate some of these concerns, and adding a dependency to Trackable Entities to support change-tracking and batch updates across service boundaries.  For my part, I have chosen to implement a limited set of generic functions for internal use by separate repository classes, which provide a meaningful public-facing contract. This approach achieves a degree of code reuse, reducing the amount of code needing to be written by developers, while not protecting them too much from the complexities of implementing the repository and unit of work design patterns.

The way I try to help developers is with good tooling, documentation and samples. On the tooling side, I have incorporated multi-project Visual Studio templates into a VSIX installer that includes all the necessary NuGet packages.  Trackable Entities now includes a New Project template called “Trackable Web Api with Repository and Unit of Work”.

Repo-UoW-NewProject

Selecting this template will create a Visual Studio 2013 solution with 6 projects:

  1. ConsoleClient
  2. Client.Entities
  3. Service.Entities
  4. Service.EF
  5. Service.Persistence
  6. WebApi

The really cool thing about this template is that all the references between projects have been set, and all the NuGet packages have been installed from the VSIX package.  While there is a sample application you can download from the CodePlex project web site, the VS template provides a mostly blank slate from which to start building your n-tier application using Trackable Entities.  To guide you through this process, I have composed a Getting Started Guide for Trackable Entities with Repository and Unit of Work Patterns, which has step-by-step instructions with screen shots and code samples for creating an end-to-end solution with a .NET client that leverages ChangeTrackingCollection<T> for automatic change-tracking and batch updates to an ASP.NET Web API service, with inserts, updates and deletes performed within a single transaction and a single round-trip.

Another power feature of the Trackable Entities extension is a set of Visual Studio item templates for creating various pieces of the Repository and Unit of Work pattern.

Entity-Repo-Interface

This screenshot shows six item templates related to Repository and Unit of Work.  There are three interface templates: Entity Repository Interface, Example Unit of Work Interface, and Database Context Interface.  And there are three class templates: Entity Repository Class, Example Unit of Work Class, and Entity Web API Controller.

These templates represent my decision to require a fair amount of work on the part of the developer, who will still need to define how the repository contracts should look and what operations should be allowed against the data store.  However, much of the repetitive boilerplate code is generated by the template, providing a greater degree of developer productivity, while serving as a learning tool on best practices for implementing these design patterns.

For example, the Service.Persistence project contains Repositories and UnitsOfWork folders for interfaces used by the Web API project to abstract away the Entity Framework.  When you add an “Entity Repository Interface”, you are presented with a wizard dialog showing all of the referenced trackable entities in a convenient drop down list.

Entity-Repo-ICustomer

This will generate a repository interface with a few basic operations.  These are asynchronous by default, but you can change them to synchronous ones if you prefer (in case you are using a data access API that does not support async.)

public interface ICustomerRepository : IRepository<Customer>, IRepositoryAsync<Customer>
{
    Task<IEnumerable<Customer>> GetCustomers();
    Task<Customer> GetCustomer(string id);
    Task<bool> DeleteCustomer(string id);
}

Selecting “Database Context Interface” will result in an interface that represents a DbContext-derived class to a concrete Entity Repository Class.

public interface INorthwindSlimContext
{
    IDbSet<Category> Categories { get; set; }
    IDbSet<Customer> Customers { get; set; }
    IDbSet<Order> Orders { get; set; }
    IDbSet<OrderDetail> OrderDetails { get; set; }
    IDbSet<Product> Products { get; set; }
}

The “Entity Repository Class” item template will generate a class that implements the corresponding repository interface and extends a lightweight generic Repository<TEntity> class for performing basic CRUD operations.  The Data Context Interface is injected into the constructor of the Entity Repository Class.

public class CustomerRepository : Repository<Customer>, ICustomerRepository
{
    private readonly INorthwindSlimContext _context;

    public CustomerRepository(INorthwindSlimContext context) :
        base(context as DbContext)
    {
        _context = context;
    }

    public async Task<IEnumerable<Customer>> GetCustomers()
    {
        IEnumerable<Customer> entities = await _context.Customers
            .ToListAsync();
        return entities;
    }

    public async Task<Customer> GetCustomer(string id)
    {
        Customer entity = await _context.Customers
            .SingleOrDefaultAsync(t => t.CustomerId == id);
        return entity;
    }

    public async Task<bool> DeleteCustomer(string id)
    {
        Customer entity = await GetCustomer(id);
        if (entity == null) return false;
        Set.Attach(entity);
        Set.Remove(entity);
        return true;
    }
}

Selecting “Example Unit of Work Class” gives you the outline of a class that implements an IUnitOfWork interface, injecting the necessary interfaces into the constructor, exposing repositories as properties, and calling SaveChanges in order to persist changes across one or more repositories.

public class NorthwindUnitOfWork : UnitOfWork, INorthwindUnitOfWork
{
    private readonly ICustomerRepository _customerRepository;
    private readonly IOrderRepository _orderRepository;

    public NorthwindUnitOfWork(INorthwindSlimContext context,
        ICustomerRepository customerRepository,
        IOrderRepository orderRepository) :
        base(context as DbContext)
    {
        _customerRepository = customerRepository;
        _orderRepository = orderRepository;
    }

    public ICustomerRepository CustomerRepository
    {
        get { return _customerRepository; }
    }

    public IOrderRepository OrderRepository
    {
        get { return _orderRepository; }
    }

    public override Task<int> SaveChangesAsync()
    {
        return base.SaveChangesAsync();
    }

    // Other methods elided for clarity
}

While these templates provide general guidance for implementing Repository and Unit of Work patterns, the “Entity Web API Controller” template will save a you a great deal of coding.  This template injects the Unit of Work interface and generates GET, PUT, POST and DELETE operations which use the interface for persistence.  Here is an excerpt of a generated controller class.

public class CustomerController : ApiController
{
    private readonly INorthwindUnitOfWork _unitOfWork;

    public CustomerController(INorthwindUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    // GET api/Customer
    [ResponseType(typeof(IEnumerable<Customer>))]
    public async Task<IHttpActionResult> GetCustomers()
    {
        IEnumerable<Customer> entities = await _unitOfWork.CustomerRepository.GetCustomers();
        return Ok(entities);
    }

    // GET api/Customer/5
    [ResponseType(typeof(Customer))]
    public async Task<IHttpActionResult> GetCustomer(string id)
    {
        Customer entity = await _unitOfWork.CustomerRepository.GetCustomer(id);
        if (entity == null)
        {
            return NotFound();
        }
        return Ok(entity);
    }

The WebApi project uses TinyIoC to resolve all the dependencies so that they are properly injected.  It contains a TinyIoCDependencyResolver, which implements IDependencyResolver and is assigned to HttpConfiguration.DependencyResolver in an IoCConfig class with a Register method that is called from Global.asax.cs.  The Register method is where you register types with the IoC container and specify a lifetime model that is tied to each Http request.

public static class IoCConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Get IoC container
        var container = TinyIoCContainer.Current;

        // Register context, unit of work and repos with per request lifetime
        container.Register<INorthwindSlimContext, NorthwindSlimContext>().AsPerRequestSingleton();
        container.Register<INorthwindUnitOfWork, NorthwindUnitOfWork>().AsPerRequestSingleton();
        container.Register<ICustomerRepository, CustomerRepository>().AsPerRequestSingleton();
        container.Register<IOrderRepository, OrderRepository>().AsPerRequestSingleton();

        // Set Web API dep resolver
        config.DependencyResolver = new TinyIoCDependencyResolver(container);
    }
}

Another cool thing is that the WebApi project installs the Web API Help Page and Test Client packages, so that running the WebApi project shows an API link that displays all the Web API operations.

Web-Api-Help

Clicking on an operation will show a page with JSON and XML response formats, as well as a “Test API” button, which you can click to invoke the operation.  For example, invoking GET api/Order?customerid={customerid} will return orders for a specific customer.

Web-Api-Help-Cust-Orders

The web Test Client will let you know if your service is up and running, but to see change-tracking in action, you’ll want to run the ConsoleClient app, which contains sample code using a service that updates the NorthwindSlim sample database.  Uncommenting code in Program.Main and setting the service port number will let you retrieve entities, as well as create, update and delete graphs of entities.  The client-side change-tracker (deployed in a portable NuGet package) will set tracking state on entities automatically as their properties are set (via INotifyPropertyChanged), or when they are added or removed from a ChangeTrackingCollection (which extends ObservableCollection).  The Client.Entities project will contain classes that implement the ITrackable interface and are reverse engineered from a database.  Child properties on entities, such as Order.OrderDetails, surface as ChangeTrackingCollections, so that child entities are automatically change-tracked.

// Start change-tracking the order
var changeTracker = new ChangeTrackingCollection<Order>(createdOrder);

// Modify order details
createdOrder.OrderDetails[0].UnitPrice++;
createdOrder.OrderDetails.RemoveAt(1);
createdOrder.OrderDetails.Add(new OrderDetail
{
    OrderId = createdOrder.OrderId,
    ProductId = 3,
    Quantity = 15,
    UnitPrice = 30
});

// Submit changes
var changedOrder = changeTracker.GetChanges().SingleOrDefault();
var updatedOrder = UpdateOrder(client, changedOrder);

// Merge changes
changeTracker.MergeChanges(ref createdOrder, updatedOrder);
Console.WriteLine("Updated order:");
PrintOrderWithDetails(createdOrder);

This code change tracks an order as details are modified, removed, added, or left unchanged. GetChanges returns just the entities that have changed, including deleted items that have been cached. This avoids sending unchanged items to the server and wasting network bandwidth. Updated entities are returned from the service, so that database-generated values are included (such as identity and concurrency values). MergeChanges merges changes and unchanged entities back together.  In contrast with now deprecated EF Self-Tracking Entities, Trackable Entities are extremely lightweight, containing only two properties: TrackingState (an enum) and ModifiedProperties (a string array used for partial updates). Because merging changes is explicit (with unchanged items merged back into the change set), there is no need for an entity dictionary, and no need for a key property attributes on on each entity.  Aside from change-state, entities can therefore remain entirely ignorant of persistence concerns.

If using Repository and Unit of Work patterns is overkill for your scenario, you can still use the “Trackable Web API” project template, which is quite a bit easier to set up and uses custom T4 templates with MVC scaffolding for generating Api Controllers with Entity Framework code for persistence.  For information on how to do that, just refer to the Trackable Web API Getting Started Guide and screencast.  (If you’re using WCF, you can refer to the Trackable WCF Getting Started Guide.)  Enjoy!

About Tony Sneed

Sr. Software Solutions Architect, Hilti Global Application Software
This entry was posted in Technical and tagged , , . Bookmark the permalink.

3 Responses to Trackable Entities – Now with Repository and Unit of Work

  1. onefootswill says:

    Hi Tony. I recently discovered Long’s project and subsequently yours. I’ve usually rolled my own in the past but you guys have done some really nice work. Did you and Long effectively merge your projects, or is your repository/unit of work different from his? Cheers.

    • Tony Sneed says:

      Hi! Thanks for the kudos. The way we decided to go was for Long to take a dependency on Trackable Entities, and at the same time for me to implement a lightweight generic Repo-UoW within TE. Our aims overlap but are slightly different. He puts more into the generic classes and uses IQueryable. I decided to give a bit more responsibility to the developer and provide more help from the tooling side in the Visual Studio templates.

      • onefootswill says:

        Thanks Tony. I actually felt bad about leaving the comment as the answer to my question became obvious as I read more and poked around in the code. The community is very lucky to have blokes like you putting out stuff like this. Some of us don’t have senior colleagues to learn from, as we don’t work in teams. We therefore rely on articles, blogs and great projects to bring our skills forward. Thanks again for your great contribution.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.