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!

Posted in Technical | Tagged , , | Leave a comment

Android and iOS Development with Simple MVVM Toolkit? Yes you can!

Note: This is Part 1 of a three part series.  This post deals with iOS development. Part 2 will delve into Android development, and Part 3 will discuss how to create a Simple Mvvm Portable Library with code that can be shared across multiple UI platforms (both Microsoft and non-Microsoft).

In the three years since its first release, my Simple MVVM Toolkit has garnered quite a bit of interest from the developer community and has had over 41,000 downloads (including CodePlex, Visual Studio Extensions Gallery, and NuGet).  My goal in creating the toolkit was simplicity in design, a rich feature set, clear documentation, plenty of samples, and an easy-to-use installer with good Visual Studio integration, including project templates and code snippets.  Since I wrote a comparison with MVVM Light, the list of differences has narrowed since Laurent added more features and has provided an installer, but the two toolkits still differ in terms of philosophy and approach. Like anything in life, it comes down to a matter of preference and personal taste.

That is, until now. Smile  Today you can use Simple MVVM Toolkit to build iOS and Android applications using the Xamarin extension to Visual Studio.  Not only that, but my toolkit includes project templates for creating Portable Class Libraries with models, view-models and other common code that can be shared across multiple UI platforms, including WPF, Silverlight, Windows Store, Windows Phone, iOS and Android.  What has made this possible is that Microsoft removed the platform restriction on NuGet packages and PCL’s can now target iOS and Android via Xamarin. (I’ll explore in depth how to use Simple MVVM Toolkit to create portable libraries in a future blog post.)

Before getting started with iOS development, you’ll probably want to go buy a Mac.  You could theoretically create a Mac OSX virtual machine on a PC, although Apple only approves virtualization on its own hardware.  Another alternative is to use a cloud-based Mac, but that could be slow, depending on your Internet connection, and isn’t free.  If you have the funds, investing in a real Mac is a great idea, and the Mac Mini starts at just $599.  I bought a top-end MacBook Air, and I run Windows 8.1 in a virtual machine on it using Parallels.  Not only do I enjoy extended battery life and superbly designed hardware, but running Windows in a VM lets me switch images, or install a new one should it become corrupted. And the solid state drive is several times faster than a SATA drive, although I still use an external SATA with a Thunderbolt cable for storing movies and other media.

Next you’ll need to install two versions of Xamarin: one on the Mac, and the other on Windows.  With both of these you’ll get Xamarin Studio, but with Windows you’ll also get Visual Studio integration.  The catch is that VS integration requires a Business Edition license, which is not free.  Nevertheless, you can start with a 30 day trial and go from there.  (MSDN subscribers get a 90 day trial and discount on the retail price, as well as exclusive training content.)  Speaking of training, be sure to check out sessions by Mark Smith on iOS and Android development with Xamarin and C#.  The view the videos, just sign up for a free 14 day trial using the promo code: SNEED-14.

Finally, install Simple MVVM Toolkit v5.5 (or later). You can get it right from within Visual Studio 2013, by selecting Tools, Extensions and Updates, clicking the Online tab, and searching for simplemvvm.  Or you can visit the download page of the Simple Mvvm Toolkit CodePlex site, where you can get the VSIX installer and run it, as well as zip files containing the samples and source code.  Note that VS 2013 Profession Edition or higher is required – as Xamarin does not support VS Express.  (There is also a separate installer for VS 2012 available on the VS Extensions Gallery which you can use with the Pro Edition, but it does not [yet] have support for Xamarin.)  While it is possible to use Xamarin Studio instead of Visual Studio, and simply reference the Simple MVVM Toolkit NuGet package, the only way to get the predefined Simple Mvvm project templates is to use VS Pro Edition together with Xamarin for Visual Studio Business Edition (licensed or free trial).

SimpleMvvm-VS-Ext

After installing Xamarin and Simple MVVM Toolkit, all you have to do is create a new Simple Mvvm iOS Application, by adding a new project, then selecting a project type of Visual C#, iOS, Universal, and choosing Simple Mvvm iOS Application (you will also see it under the general Visual C# category).

SimpleMvvm-iOS

You will then be prompted to connect to a Xamarin.iOS Build Host, running on a Mac (local or networked).

iOS-BuildHost

What you get is a fully functioning iOS application for both iPhone and iPad using the Simple MVVM Toolkit! Just select iPhoneSimulator as your configuration and press F5.  That will open up the sample app on your Mac in the iPhone simulator.

SimpleMvvm-iOS-Mac

To see the same app running in the iPad simulator, open the solution file (.sln) using Xamarin Studio for the Mac (I didn’t see an iPad configuration option in Visual Studio), select Debug / iPad iOS 7.0, and click the Run button.

SimpleMvvm-iPad-Mac

There is a lot going on under the covers to make all this happen.  First, there’s the visual layout.  I created the layout using storyboards in Xamarin Studio for the Mac.  For that I had to select “Check for Updates” from the Xamarin Studio menu and get the latest version from the Alpha channel (eventually this feature will be released on the Stable channel).  I started with a Single View App based on the Universal Storyboard template.

SimpleMvvm-Univ-Storyboard

This allowed me to create two storyboards, one for iPhone and the other for iPad.  The visual designer is quite good – I could drag items from the toolbox and set properties.  Setting the Name property on an element results in a code-generated property representing the element in the view controller code-behind class, which is needed to wire up data binding.

SimpleMvvm-Storyboard-Designer

To be able to bind UI elements to view model properties, there are a number of steps that need to be performed.  Data binding takes place using classes provided by the MvvmCross “Core” NuGet package.  Luckily, the Simple Mvvm template already contains most of the necessary code, including a BindingSetup class for initializing the IOC container and registering the binding builder, as well as code in the view controller class for setting the view model as the DataContext.  The only code you’ll need to write is for binding each element to a corresponding view model property from within the ViewDidLoad method.

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    // Bindings setup helper
    var bindingSet = this.CreateBindingSet<SimpleMvvm_iOSViewController, CustomerViewModel>();

    // Properties
    if (BannerLabel_iPhone != null)
        bindingSet.Bind(BannerLabel_iPhone).To(vm => vm.BannerText);

    // Command
    if (NewCustomerButton_iPhone != null)
        bindingSet.Bind(NewCustomerButton_iPhone).To(vm => vm.NewCustomerCommand);

    // Apply bindings
    bindingSet.Apply();
}

In case you don’t have the Xamarin Business Edition with VS support, you will need to use the Mac version of Xamarin Studio (the Windows version of Xamarin Studio does not currently support iOS development).  Then you will need to add the Simple Mvvm Toolkit and MvvmCross Core NuGet packages (first enable the NuGet add-in for Xamarin Studio on the Mac), and manually copy code from the Simple Mvvm iOS template.

In my next blog post I’ll dive into using Simple MVVM Toolkit for developing Android applications using Xamarin.  Before long, you’ll be on your way to building that next killer app for iOS, Android and Windows.  All the best!

Posted in Technical | Tagged | 3 Comments

Trackable Entities versus Self-Tracking Entities

In this blog post I’d like to perform an in-depth comparison between my own Trackable Entities framework and the now deprecated Self-Tracking Entities, written by the Entity Framework team at Microsoft. Because STE’s were discontinued with EF v4, there’s the mistaken notion that tracking entity state is generally a bad idea. Nothing could be further from the truth.

Consider the following scenario. You have an Order entity with related OrderDetails. You want to create, update and delete some of the OrderDetails within the same transaction. If one of the updates fails, for example by not specifying a valid ProductId, none of the other updates should succeed, and the entire transaction should be rolled back.  This means you need to pass all the details (added, modified, deleted) to the same service operation. Without tracking entity state, you would have to pass each set of details separately. For example:

public Order PutOrder(Order order, List<OrderDetail> addedDetails,
    List<OrderDetail> modifiedDetails, List<OrderDetail> deletedDetails)
{
    // TODO: Save changes
}

On the client you still have to keep track of which details were added, modified and deleted, so that you can group them accordingly. Then on the server you have to figure out how best to return inserted and updated details to the client with database-generated identity and concurrency values, probably by retrieving the updated order with details from the database.

Change-tracking solves this problem.  In fact, this is precisely how WCF Data Services, an implementation of the OData spec, performs batch updates.  There is a client-side change-tracker which sets entity state as you call methods on a context object (AddObject, UpdateObject, DeleteObject, SetLink), so that updates can be batched when changes are saved.  In fact, WCF Data Services is one of the technologies recommended by Microsoft as a replacement for STE’s.  Nevertheless, OData is not necessarily going to give you as much control over the API surface of your web services. While it is possible to expose an OData service via ASP.NET Web API controllers, the overall intent of OData is to create queryable syndication data feeds – using OData just to get change-tracking and batch updates may be overkill for most n-tier scenarios.

So where did Self-Tracking Entities go wrong?

To answer this question, let’s take a look at code produced by the STE template.

[DataContract(IsReference = true)]
[KnownType(typeof(Category))]
[KnownType(typeof(OrderDetail))]
public partial class Product : IObjectWithChangeTracker, INotifyPropertyChanged
{
    [DataMember]
    public string ProductName
    {
        get { return _productName; }
        set
        {
            if (_productName != value)
            {
                _productName = value;
                OnPropertyChanged("ProductName");
            }
        }
    }
    private string _productName;

    [DataMember]
    public TrackableCollection<OrderDetail> OrderDetails
    {
        get
        {
            if (_orderDetails == null)
            {
                _orderDetails = new TrackableCollection<OrderDetail>();
                _orderDetails.CollectionChanged += FixupOrderDetails;
            }
            return _orderDetails;
        }
        set
        {
            if (!ReferenceEquals(_orderDetails, value))
            {
                if (ChangeTracker.ChangeTrackingEnabled)
                {
                    throw new InvalidOperationException("Cannot set the FixupChangeTrackingCollection when ChangeTracking is enabled");
                }
                if (_orderDetails != null)
                {
                    _orderDetails.CollectionChanged -= FixupOrderDetails;
                }
                _orderDetails = value;
                if (_orderDetails != null)
                {
                    _orderDetails.CollectionChanged += FixupOrderDetails;
                }
                OnNavigationPropertyChanged("OrderDetails");
            }
        }
    }
    private TrackableCollection<OrderDetail> _orderDetails;

    [DataMember]
    public ObjectChangeTracker ChangeTracker
    {
        get
        {
            if (_changeTracker == null)
            {
                _changeTracker = new ObjectChangeTracker();
                _changeTracker.ObjectStateChanging += HandleObjectStateChanging;
            }
            return _changeTracker;
        }
        set
        {
            if (_changeTracker != null)
            {
                _changeTracker.ObjectStateChanging -= HandleObjectStateChanging;
            }
            _changeTracker = value;
            if (_changeTracker != null)
            {
                _changeTracker.ObjectStateChanging += HandleObjectStateChanging;
            }
        }
    }
    private ObjectChangeTracker _changeTracker;

    // Change Tracking Code ...

    // Serialization Code ...

    // Association Fixup Code ...
}

I omitted most of the other properties, but altogether the Product class ends up with over 350 lines of code!  And most of that is plumbing code handling various aspects of change-tracking and serialization. But it gets worse. You can see that Product implements an interface called IObjectWithChangeTracker, which has a ChangeTracker property of type ObjectChangeTracker, which in turn has properties for ObjectState, ObjectsRemovedFromCollectionProperties, ObjectsAddedToCollectionProperties, OriginalValues and ExtendedProperties.

The sad part about all this is that the extra baggage added by these properties and methods is almost entirely unnecessary.  There’s no need to attach a change tracker to each entity, nor should it be necessary to insert change-tracking and serialization code into each entity.  Those things belong elsewhere. In short, STE’s violate the principle of Separation of Concerns (SoC).

Why were STE’s designed this way?  There are probably several reasons. For one, they modeled STE’s after EF-specific entities, which implement IEntityWithChangeTracker.  Second, NuGet did not exist at that time, making it difficult to deploy an assembly with a client-side change-tracker that did not depend on the Entity Framework, which forced them to use T4 code generation instead. Third, they generated the same entities for both client and server, with server code that did not belong on the client and client code that did not belong on the server. Fourth, they were still tied to a Model First approach with an EDMX file, and because Code First was not yet fully baked, they had to take Independent Associations into account. Fifth, they brought over original property values rather than requiring the use of row versions for concurrency. And sixth, the client-side code generally is too tightly coupled with the server-side code that reads the entity state in order to perform updates.

In addition, the API was rather rough around the edges.  Here is list of complaints I had at the time:

  • No GetChanges method to obtain just the entities that had changed.
  • Items removed from child collections were not automatically marked as deleted – you had to call MarkAsDeleted explicitly.
  • Marking a parent as deleted did not mark child entities as deleted – you had to do it manually.
  • AcceptChanges was not recursive – you had to call it on both parent and child entities.

The good news is that these architectural and technical flaws are avoidable.  Some of them could have been avoided at the time, and others can now be avoided because we have additional options. For example, Code First is now mature, and we have NuGet for distributing a client assembly that is not tied to Entity Framework. We still have T4 templates, but they can be used more narrowly for generating separate client and server entities.  In addition, it is now possible to leverage other tools for increasing developer productivity, such as the EF Power Tools (although they need an overhaul), and scaffolding for ASP.NET Web API.

So how does Trackable Entities avoid the pitfalls that doomed STE’s?

Before answering this question, I would like to point out that Trackable Entities actually predates STE’s and EF4. Back in 2008, I published an MSDN Magazine article which provided a solution to the need for change-tracking entities across service boundaries in a way that does not couple entities to any particular persistence stack.  (I even showed how it could be done with both EF and LINQ to SQL.)  Then in 2010 I updated my solution with Trackable DTO’s and T4 templates that generated client-entities based on WCF metadata. My Trackable Entities project represents a further evolution that is not coupled to any web service stack (be it ASP.NET Web API or Windows Communication Foundation).

Now to answer the question. Architecturally, Trackable Entities adheres to the principle of SoC by placing all change-tracking logic in a class called ChangeTrackingCollection<T>, which extends ObservableCollection<T> (for data-binding friendliness).  The change tracker marks entities as Added, Modified or Deleted (deleted items are also cached). To track some items, just add them to the collection. Simple! Smile

The client assembly is a Portable Class Library (so it runs on just about any client) and is deployed as a NuGet package. Its only dependency is on a TrackableEntities.Common package, which contains the ITrackable interface, and on Json.Net, for efficient serialization.  Here is the client version of the Product entity (with just ProjectName and OrderDetails properties – just like the STE sample I showed earlier). Aside from properties for TrackingState and ModifiedProperties, there’s no extra code for change-tracking or serialization. ModelBase only contains an implementation of INotifyPropertyChanged, and this class is not generated because it’s located in the client library referenced via NuGet.

[JsonObject(IsReference = true)]
[DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
public partial class Product : ModelBase<Product>, ITrackable
{
    public Product()
    {
        this.OrderDetails = new ChangeTrackingCollection<OrderDetail>();
    }

    [DataMember]
    public string ProductName
    {
        get { return _ProductName; }
        set
        {
            if (value == _ProductName) return;
            _ProductName = value;
            NotifyPropertyChanged(m => m.ProductName);
        }
    }
    private string _ProductName;

    [DataMember]
    public ChangeTrackingCollection<OrderDetail> OrderDetails
    {
        get { return _OrderDetails; }
        set
        {
            if (Equals(value, _OrderDetails)) return;
            _OrderDetails = value;
            NotifyPropertyChanged(m => m.OrderDetails);
        }
    }
    private ChangeTrackingCollection<OrderDetail> _OrderDetails;

    [DataMember]
    public ICollection<string> ModifiedProperties { get; set; }

    [DataMember]
    public TrackingState TrackingState { get; set; }
}

Another way that Trackable Entities achieves Separation of Concerns is by providing separate T4 templates for client and server entity generation. Client-side entities automatically track changes to client entities and implement INotifyPropertyChanged, but on the server there’s no need for such things. Here is the same Product entity generated for the server.

[JsonObject(IsReference = true)]
[DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
public partial class Product : ITrackable
{
    public Product()
    {
        this.OrderDetails = new List<OrderDetail>();
    }

    [DataMember]
    public string ProductName { get; set; }
    [DataMember]
    public List<OrderDetail> OrderDetails { get; set; }

    [DataMember]
    public TrackingState TrackingState { get; set; }
    [DataMember]
    public ICollection<string> ModifiedProperties { get; set; }
}

As you can see, there is nothing related to EF and nothing that would require tight coupling on the client. TrackingState is simply an enum and is serialized (Json or Xml) as an Integer. ModifiedProperties is represented as a collection of strings and is only present on modified entities.

On the server things are also much simpler, and everything is based on Code First, so there’s no EDMX file to contend with.  There is an ApplyChanges method you call on your DbContext-derived class, which recursively walks the object graph, setting EntityState by reading each entity’s TrackingState. Then there’s an AcceptChanges method which recursively sets entities to an Unchanged state before they are returned to the client. In total, there are just two public methods with two private helper methods and about 100 lines of code. That’s it!  In contrast, STE’s generate server-side code with 28 methods, 4 helper classes and over 1200 lines of code.

I hope this post helps developers get past any aversion they might have to change-tracking from having been burned by STE’s.  One of the alternatives to STE’s recommended by Microsoft is “Entity Framework APIs,” where they refer to an excellent book on DbContext by Julie Lerman and Rowan Miller.  But then they issue the warning that “this is a complex problem to solve” and steer you back to WCF Data Services.  I would heartily agree that it is a complex problem to solve, but it has been solved! So instead of trying to re-invent the wheel, I urge you (at the risk of sounding self-serving) to give my Trackable Entities a try. Smile

Before closing out, I’d like to mention that Trackable Entities is not just a set of NuGet packages. I’ve deployed it to the Visual Studio Gallery as extensions to both VS 2012 and VS 2013. There is also a Getting Started guide and accompanying screencast. And both ASP.NET Web API and WCF are supported.  What you get is a set of multi-project templates that spin up end-to-end solutions with templates that leverage scaffolding (for ASP.NET Web API), or provide a VS item template (for WCF), and give you service operations that handle all the CRUD. Cheers!

Posted in Technical | Tagged | 10 Comments

API Improvements in Trackable Entities v1.01

I’d like to announce version 1.01 of Trackable Entities, which fixes a few issues and adds two methods to the API.

  • DbContext.AcceptChanges: You want to call this method after performing inserts or updates in service operations (Web API or WCF), so that the state of each entity in the object graph is returned to Unchanged.  This is done so that the entity is returned to the client is ready for additional updates.
_dbContext.ApplyChanges(product);
_dbContext.SaveChanges();
product.AcceptChanges();
  • ChangeTrackingCollection.MergeChanges: This method should be called on the client-side after entities are returned from an update operation.  This is needed in the case where you first call GetChanges on the change tracker so that you can pass only changed items (inserts, updated and deletes) to a service update operation. After you get back the updated entities, you usually want to merge them back into entities which contain unchanged items which were not sent to the service. That’s where MergeChanges comes in.  MergeChanges will combine changed and unchanged items into a single set of entities, with tracking state set to Unchanged and no cached deletes.  This takes place in reverse – unchanged entities are merged into the set of entities returned by the update operation. This is needed because client-side entities are completely persistence-ignorant, and by design we don’t know which properties represent the entity key.

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

After calling MergeChanges, both createdOrder and updatedOrder point to an order entity which contains details that were not sent to the service and remain in the same state as before, as well as added, modified and deleted details that were returned from the service after having been persisted and contain database-generated values for identity and concurrency.

Posted in Technical | Tagged | Leave a comment

Simple MVVM Toolkit v 5.0 for VS 2013

Update: The VSIX installer for version 5.5.0.1 of Simple MVVM Toolkit includes the toolkit code snippets! They are included as a pkgdef (VS add-in). So after installing the toolkit, press Ctrl+K, Ctrl+X and select a C# or XAML snippet from the Mvvm folder (or just type the C# code snippet name).  Note that if you are using ReSharper, you will need to select RESHARPER, Options, Environment, Intellisense, General, and select Visual Studio.

Simple MVVM Toolkit v5.0 for Visual Studio 2013 is now published! There is support for WPF 4-4.51, Silverlight 5, Windows Store 8.1 and Windows Phone 8. Come and get it! https://simplemvvmtoolkit.codeplex.com/

Adding support for Windows Store 8.1 and Windows Phone 8 was not that difficult. This was due primarily to the work that had been done in v4 of the toolkit, namely, placing as much functionality as possible in the SimpleMvvmToolkit-Common assembly, which is a portable class library.  For the common library I set target framework compatibility to .NET Framework 4.5 and higher, Silverlight 5, Windows Phone 8, and Windows Store (Windows 8) and higher.

One thing, however, that differs among these frameworks is how to marshal code that is running on a background thread back onto the main UI thread.  For standard code-behind, this made much easier by the async / await pattern, which handles the marshaling automatically. However, it is not as easy when setting a view-model property from a background thread.  You would have to get onto the UI thread by placing the code to set the property after the await statement.  That’s not really too much to ask, but wouldn’t it be easier if you didn’t have to think about it? Shouldn’t the framework would handle the marshaling for you?

That is precisely what Simple MVVM Toolkit does. Smile But to make the magic happen, some things need to take place under the covers, and there are some differences between Silverlight and other frameworks, such as WPF, Windows Store and Windows Phone 8.  The latter require that you initialize the dispatcher while on the main UI thread. To allow this, UIDispatcher has an Initialize method, which you should call at app startup.

#if !SILVERLIGHT
    /// <summary>
    /// Invoke from main UI thread.
    /// </summary>
    public static void Initialize()
    {
        #if NETFX_CORE
        WindowsDispatcher windowsDispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
        #else
        WindowsDispatcher windowsDispatcher = WindowsDispatcher.CurrentDispatcher;
        #endif
        _dispatcher = new UIDispatcher(windowsDispatcher);
    }
#endif

One goal of mine was to add support for Windows Store and Windows Phone 8, but another pressing concern was to address the difficulties some users experienced trying to install v3 and v4 of the toolkit.  The download to those versions is an MSI installer created using InstallShield.  Unfortunately, Microsoft removed the built-in installation templates from Visual Studio, and the “express” edition of InstallShield pulled in dependencies from the machine on which the installer was created. The end result was that .NET Framework assemblies were removed by the installer when the user uninstalled the toolkit – yikes! There were also issues with the placement of the project templates in the user’s personal folder.

To address these issues and create a smother installation experience, I decided to deploy v5 of the toolkit as a VSIX – Visual Studio Extension. (I also intend to re-deploy v3 and v4 of the toolkit as VSIX’s.) This solves the main problem of unintended dependencies, as well as the placement of project templates.  It also removes the need to install the template wizard in the Global Assembly Cache, because it can be included with the VSIX installer.

This prompted me to re-think another aspect of the installer, which was creating registry entries so that the toolkit assemblies would show up in the Add References dialog.  To solve that, I turned to NuGet. It’s possible to include NuGet packages in a VSIX file and configure the project templates to pull them in. I also was able to consolidate all versions of the toolkit into a single NuGet package: SimpleMvvmToolkit.  That’s because a single package can contain multiple assemblies, each targeting a different platform. NuGet knows how to install the right assemblies based on the framework of the project using the package.

There are some trade-offs in the decision to use VSIX and NuGet. The main one is that VSIX does not support the installation of code snippets.  So what I plan to do is instead create a VSI file for the code snippets.  Secondly, it’s not practical to use a VSIX for installing things like samples and source code.  So I simply added them as separate downloads from the CodePlex site.

One last change to the toolkit is with the source code repository on CodePlex.  I had been using TFS for source code control, but the repository only included the class libraries and not other artifacts, such as NuGet packages and installers. I hesitated to redo the directory structure because of how difficult it is to do in TFS.  I also had several developers who wanted to contribute to the project, so switching to a distributed system like Git started to make sense.

It took some time to learn the in’s and out’s of Git, but the effort was well worth it. CodePlex recently added support for Git and has a nice set of instructions. I asked the kind folks at CodePlex to remove the existing TFS repo and replace it with a Git repo. After installing Git for Windows and TortoiseGit, I cloned the repo locally, added the files, committed them, and pushed them up to CodePlex. It was incredibly easy to do.

This makes it more straightforward for anyone wanting to contribute to the project.  All you have to do is fork it, create a local branch, make your changes, then issue a pull request, which I can evaluate and them merge into the main branch.

Enjoy.

Posted in Technical | Tagged | Leave a comment

Trackable Entities Version 1.0 Released!

I am pleased to announce the release of Trackable Entities version 1.0 – with support for both WCF and ASP.NET Web API with Visual Studio 2012 and 2013!

VS 2013 Extensions

The idea behind this tool is simple: enable you to build n-tier applications quickly and easily, with entities that are change-tracked on the client in a persistence-ignorant fashion, then sent to a web service where they can be updated in a batch operation within a single transaction.  The classic example is an Order with OrderDetails.  The parent order may or may not have any changes, but the details could include new items, removed items and modified items.  These should be persisted in an atomic fashion within the same transaction.  If saving one of the items fails (for example because of invalid data), then all the updates should be rolled back.

Let’s start off with getting one thing straight: these have nothing to do with the now defunct Self-Tracking Entities that were once part of the Entity Framework.  The goal of that project was noble, but the implementation was flawed, resulting in bloated code with rather tight coupling to the framework, similar to when ADO.NET DataSets were used to send entities across service boundaries.  The problem is that, because STE’s were implemented poorly, the very idea of client-side change-tracking and batch updates fell out of favor.  To add insult to injury, the EF team decided to deprecate STE’s instead of redesigning them.

This is where my solution to the problem comes in: Trackable Entities.  Contrary to STE’s, Trackable Entities are completely platform neutral and carry very little overhead: just an enum property for entity state, and optionally a list of properties that have been modified (which is needed for partial updates to the database).  Another difference is that instead of inserting a change-tracker into each entity (like STE’s did), Trackable Entities sports a separate ChangeTrackingCollection<T>, which is responsible for setting entity state transparently, as items are added, removed or modified.  And it has a GetChanges method, so that only entities that have changes are sent to the server, instead of all the entities (like STE’s did).

But if Microsoft dropped support for Self-Tracking Entities, doesn’t that mean change-tracking and batch updates for entities is generally a bad idea?  Well, tell that to the OData team, which included these features in Data Services.  That product has a client-side change tracker which adds metadata to requests for batch updates.

So why not just use OData? The purpose of OData is essentially to expose an entity data model as a REST service. But you end up basically exposing your database to ad hoc queries, which may not be what you want.  My approach instead builds on the service model of ASP.NET Web API, with a T4 template for generating controller actions for data persistence.  This give you a great deal more control.

The core functionality of Trackable Entities is deployed as a set of NuGet packages, but the killer feature is the productivity tools provided by the project templates installed by a VSIX Visual Studio extension.  There are two child project templates: Client.Entities, a portable class library compatible with .NET 4, SL5, WP8 and Win8.  It includes a custom T4 template, which is executed by the Entity Framework Power Tools when reverse engineering database tables into Code First entities.  This template generates classes that implement INotifyPropertyChanged and ITrackable, so that the ChangeTrackingCollection can do its magic.  Similarly, there is a Service.Entities project template includes a T4 template which the EF Power Tools uses to generate server-side entities.

VS 2013 Projects

While those project templates are nice, they aren’t the best part. There are also multi-project templates for creating turn-key n-tier applications based on either WCF or ASP.NET Web API.  When you create a project based on one of these two templates, you get custom T4 templates for generating services with CRUD operations.  For Web API, you add the same template as you would for a Controller that uses Entity Framework.

vs2013-api2

The T4 template, however, generates code that is much better than what the default template generates.  For example, POST (insert) and PUT (update) methods each return an updated entity that includes database-generated values (for identity or concurrency).  Also, my T4 template inserts Include operators for bringing back related entities (for example, Product would include the related Category entity).  (You need to add Includes for child entities yourself.)

Here’s an example of the Web API Controller generated for the Product entity.

public class ProductController : ApiController
{
    private readonly NorthwindSlimContext _dbContext = new NorthwindSlimContext();

    // GET api/Product
    [ResponseType(typeof(IEnumerable<Product>))]
    public async Task<IHttpActionResult> GetProducts()
    {
        IEnumerable<Product> products = await _dbContext.Products
            .Include(p => p.Category)
            .ToListAsync();

        return Ok(products);
    }

    // GET api/Product/5
    [ResponseType(typeof(Product))]
    public async Task<IHttpActionResult> GetProduct(int id)
    {
        Product product = await _dbContext.Products
            .Include(p => p.Category)
            .SingleOrDefaultAsync(p => p.ProductId == id);

        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    // PUT api/Product
    [ResponseType(typeof(Product))]
    public async Task<IHttpActionResult> PutProduct(Product product)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        try
        {
            // Update object graph entity state
            _dbContext.ApplyChanges(product);
            await _dbContext.SaveChangesAsync();
            return Ok(product);
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!_dbContext.Products.Any(p => p.ProductId == product.ProductId))
            {
                return NotFound();
            }
            throw;
        }
    }

    // POST api/Product
    [ResponseType(typeof(Product))]
    public async Task<IHttpActionResult> PostProduct(Product product)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        _dbContext.Products.Add(product);
        await _dbContext.SaveChangesAsync();

        var ctx = ((IObjectContextAdapter) _dbContext).ObjectContext;
        ctx.LoadProperty(product, p => p.Category);

        return CreatedAtRoute("DefaultApi", new { id = product.ProductId }, product);
    }

    // DELETE api/Product/5
    public async Task<IHttpActionResult> DeleteProduct(int id)
    {
        Product product = await _dbContext.Products
            .Include(p => p.Category)
            .SingleOrDefaultAsync(p => p.ProductId == id);
        if (product == null)
        {
            return NotFound();
        }

        _dbContext.Products.Attach(product);
        _dbContext.Products.Remove(product);

        try
        {
            await _dbContext.SaveChangesAsync();
            return Ok();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!_dbContext.Products.Any(p => p.ProductId == product.ProductId))
            {
                return NotFound();
            }
            throw;
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _dbContext.Dispose();
        }
        base.Dispose(disposing);
    }
}

While Web API integration is a sweet spot of the Trackable Entities Visual Studio extension, I’ve also included support for Windows Communication Foundation. First, entities are decorated with [DataContract(IsReference = true)].  Second, there is an item template called TrackableWcfServiceType, which inserts a WCF service contract interface and implementation for async CRUD operations.  Here is the code generated for the Product service.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class ProductService : IProductService, IDisposable
{
    private readonly NorthwindSlimContext _dbContext;

    public ProductService()
    {
        _dbContext = new NorthwindSlimContext();
    }

    public async Task<IEnumerable<Product>> GetProducts()
    {
        IEnumerable<Product> entities = await _dbContext.Products
            .ToListAsync();
        return entities;
    }

    public async Task<Product> GetProduct(int id)
    {
        Product entity = await _dbContext.Products
            .SingleOrDefaultAsync(x => x.ProductId == id);
        return entity;
    }

    public async Task<Product> UpdateProduct(Product entity)
    {
        try
        {
            // Update object graph entity state
            _dbContext.ApplyChanges(entity);
            await _dbContext.SaveChangesAsync();
            return entity;
        }
        catch (DbUpdateConcurrencyException updateEx)
        {
            throw new FaultException(updateEx.Message);
        }
    }

    public async Task<Product> CreateProduct(Product entity)
    {
        _dbContext.Products.Add(entity);
        await _dbContext.SaveChangesAsync();
        return entity;
    }

public async Task<bool> DeleteProduct(int id)
    {
        Product entity = await _dbContext.Products
            .SingleOrDefaultAsync(x => x.ProductId == id);
        if (entity == null)
            return false;

        try
        {
            _dbContext.Products.Attach(entity);
            _dbContext.Products.Remove(entity);
            await _dbContext.SaveChangesAsync();
            return true;
        }
        catch (DbUpdateConcurrencyException updateEx)
        {
            throw new FaultException(updateEx.Message);
        }
    }

    public void Dispose()
    {
        var dispose = _dbContext as IDisposable;
        if (dispose != null)
        {
            _dbContext.Dispose();
        }
    }
}

The nice thing about native clients, be they traditional desktop applications or handheld devices, is that they deal with data in a disconnected fashion, making batch updates a necessity.  That means it would be up to you to figure out which entities are inserted, updated or deleted, then send them separately to the service for persistence.  Trackable Entities gives you client-side change-tracking and an elegant model for server-side persistence, without the extra baggage of a framework like OData.  Plus you get a very nice set of templates for generating server-side persistence code.  Enjoy.

Posted in Technical | Tagged , , , | 12 Comments

Trackable Entities: N-Tier Support for Entity Framework

tracking-logo

Writing N-Tier apps can get complicated fast.  Consider the assortment of n-tier technologies now consigned to the ash heap of history: WCF RIA Services, Self-Tracking Entities, and good old typed DataSets.  These have all suffered from lack of interoperability and tight coupling with technologies that were later deprecated.  DataSets were coupled to the .NET Framework, RIA Services was tightly integrated with Silverlight, and Self-Tracking Entities bit the dust with EF5 when CodeFirst was released and the team didn’t want to upgrade a solution that was somewhat flawed to begin with.

The problem all these approaches attempted to solve is how to commit a batch of entity updates in a single transaction with a single round-trip to the server.  For example, if I have an order with associated details, and I alter the order details by modifying one of the details, removing one, and inserting a new detail, I would like to send the order to a service operation where all the updates can take place atomically.  One approach would be to separate out each set of changes and add them as parameters.  For example: UpdateOrder(Order order, OrderDetail[] addedDetails, OrderDetail[] modifiedDetails, OrderDetail[] deletedDetails).  But that would require me to massage the order by removing all the details and creating different collections of details based on the types of changes, and I would have to cache deleted entities so they could be passed in separately.  That involves a fair amount of tedious work, and the service API becomes rather clunky. It would be preferable for my service to expose an UpdateOrder operation that simply accepts an Order with details that have been added, modified or deleted.

public Order UpdateOrder(Order order)
{
    // Add, update and delete order details ...
}

The trick is to pass entity state along, but to do so in a way that is technology and platform agnostic and that does not add much overhead to the operation.  There is a technology that achieves this goal: OData, implemented by WCF Data Services and OData for ASP.NET Web API.  But the intent of OData and Data Services is to expose an Data Model (EF or an alternative source) as a REST-based service and is geared toward rendering data as a syndication feed.  While this is certainly a plausible choice, it might be overkill for scenarios where you simple want to expose a set of fine-grained operations.

A simpler and more straightforward approach would be to attach a little bit of metadata to each entity to indicate its state.  Then read that state on the server-side, performing all the updates in a single transaction.  That is the purpose of my new library and Visual Studio 2012 extension: Trackable Entities.

new-trackable-project

The easiest way to get it is to install it from within Visual Studio: Tools, Extensions and Updates, Online Visual Studio Gallery, then search for “Trackable”.  But you can get more goodness by visiting the Trackable Entities CodePlex site where you can download samples and source code. (Note that a prerequisite for the VS extension is the Entity Framework Power Tools.)

trackable-vs-gallery

Core functionality is contained in a set of TrackableEntities NuGet packages, which provide both client-side change-tracking and a server-side DbContext extension which can walk an object graph and inform the DbContext of each entity’s state so it can be persisted in a transaction when SaveChanges is called.  The client Nuget package has a ChangeTrackingCollection<T>, which extends ObservableCollection<T> by monitoring entity changes and marking them as Added, Modified or Deleted.  There is a GetChanges that returns a cloned object graph containing only changed entities.  The client-side package is implemented as a Portable Class Library which supports .NET 4.5, Silverlight 4-5, Windows Phone 7-5 or greater, and Windows Store applications.

Entity state is tracked by means of the ITrackable interface:

public interface ITrackable
{
    TrackingState TrackingState { get; set; }
    ICollection<string> ModifiedProperties { get; set; }
}

TrackingState is simply an enum, and ModifiedProperties contains a list of properties that have been updated on an entity, so that only changed properties can be persisted.

public enum TrackingState
{
    Unchanged,
    Added,
    Modified,
    Deleted
}

While the NuGet packages provide change-tracking and persistence capability, the sweet spot for productively using these libraries lies in the Trackable Entities Visual Studio 2012 extension, deployed as a VSIX file that installs a number of Visual Studio project templates.  First there is a Client Entities template, which creates a portable library and includes a T4 template for reverse engineering client entities using Entity Framework Power Tools.  Keep in mind that on the client you will remove all EF-specific classes and packages after running the tool, and there will be no coupling to EF on the client, or any other persistence technology for that matter.  (I have submitted a feature request to the EF team for allowing the EF Power Tools to generate entities separately from EF-specific classes, so they can be placed in an assembly that does not reference EF.)  Each generated entity implements both ITrackable and INotifyPropertyChanged interfaces to facilitate change-tracking, and child collections are typed as ChangeTrackingCollection<T>, so that they are properly change-tracked. For example, here is the Order entity reverse engineered from the Northwind database.

[JsonObject(IsReference = true)]
[DataContract(IsReference = true, Namespace = "http://schemas.datacontract.org/2004/07/TrackableEntities.Models")]
public partial class Order : ModelBase<Order>
{
    [DataMember]
    public int OrderId
    { 
        get { return _OrderId; }
        set
        {
            if (value == _OrderId) return;
            _OrderId = value;
            NotifyPropertyChanged(m => m.OrderId);
        }
    }
    private int _OrderId;

    [DataMember]
    public string CustomerId
    { 
        get { return _CustomerId; }
        set
        {
            if (value == _CustomerId) return;
            _CustomerId = value;
            NotifyPropertyChanged(m => m.CustomerId);
        }
    }
    private string _CustomerId;

    [DataMember]
    public Customer Customer
    {
        get { return _Customer; }
        set
        {
            if (value == _Customer) return;
            _Customer = value;
            NotifyPropertyChanged(m => m.Customer);
        }
    }
    private Customer _Customer;

    [DataMember]
    public ChangeTrackingCollection<OrderDetail> OrderDetails
    {
        get { return _OrderDetails; }
        set
        {
            if (Equals(value, _OrderDetails)) return;
            _OrderDetails = value;
            NotifyPropertyChanged(m => m.OrderDetails);
        }
    }
    private ChangeTrackingCollection<OrderDetail> _OrderDetails;
}

ITrackable and INotifyPropertyChanged interfaces are implemented in ModelBase<T>, which has a property NotifyPropertyChanged method that accepts lambda expressions.  You might also notice the use of [DataContract] and [JsonObject] attributes, which support serialization of cyclical references with an IsReference property when it is set to True.

On the server side you can use the Service Entities project template to create a .NET 4.5 class library. It also has a set of T4 templates for use with the EF Power Tools that reverse engineer CodeFirst classes and entities that implement ITrackable.  It comes with an ApplyChanges extension method to DbContext which walks an entity object graph, reads the tracking state and sets the entity state.  It can be tricky to apply state changes in the right order as you recursively traverse an object graph, but the extension method takes care of that for you so you don’t have to worry about it.  All you do is call ApplyChanges just before SaveChanges, and you’re good to go.

var db = new NorthwindContext();
db.ApplyChanges(order);
db.SaveChanges();

The Client and Service Entities project templates give you an amazing amount of functionality, but there’s more!  The Trackable Entities extension also installs a Trackable Web Api multi-project template, which includes both the Client and Service Entities projects, as well as an ASP.NET Web API project with a T4 template that customizes code generation when you add a controller.  The call to ApplyChanges is inserted in the right place, and there are other improvements to the default template.  For example, the Put method returns the updated entity so that concurrency checks will take place, Post loads related entities, and Delete loads child entities.

add-controller

The Web API template also includes a console client project that references the Client Entities project and uses HttpClient to invoke service operation on change-tracked entities.  It includes a ReadMe file with step-by-step instructions to get you started.  Here are some helper methods produced for the console client, which can be ported to any kind of .NET client (for example, WPF, Phone, or Windows Store app).

// TODO: Replace 'Entities', 'Entity', 'EntityId, 'entity' with class name (for ex, Order)

private static Entity GetEntity(HttpClient client, int entityId)
{
    string request = "api/Entities/" + entityId;
    var response = client.GetAsync(request).Result;
    response.EnsureSuccessStatusCode();
    var result = response.Content.ReadAsAsync<Entity>().Result;
    return result;
}

private static Entity CreateEntity(HttpClient client, Entity entity)
{
    string request = "api/Entities";
    var response = client.PostAsJsonAsync(request, entity).Result;
    response.EnsureSuccessStatusCode();
    var result = response.Content.ReadAsAsync<Entity>().Result;
    return result;
}

private static Entity UpdateEntity(HttpClient client, Entity entity)
{
    string request = "api/Entities";
    var response = client.PutAsJsonAsync(request, entity).Result;
    response.EnsureSuccessStatusCode();
    var result = response.Content.ReadAsAsync<Entity>().Result;
    return result;
}

private static void DeleteEntity(HttpClient client, Entity entity)
{
    string request = "api/Entities/" + entity.EntityId;
    var response = client.DeleteAsync(request);
    response.Result.EnsureSuccessStatusCode();
}

I began thinking about trackable entities way back in 2008, when I published an MSDN Magazine article exploring the topic, and then again in 2010 when I updated the code and incorporated T4 templates which read WCF service metadata.  These ideas are carried forward with this project, but it is not tied to WCF and allows for any service or persistence framework (it could, for example, be extended for NHibernate and other object-relational mappers).  The main design goal is to provide a robust client-side change tracker and code-generation of persistence-ignorant classes (POCO) that carry state information with minimal overhead and are fully interoperable.  Service entities are generated independently so they can be mapped to a data context, and they can implement ITrackable without referencing the client library.

The code is fairly stable and there is good code coverage with unit and integration tests, but I’ve released the NuGet packages and VS extension as beta (you need to include Prerelease packages to find it) so that you can start playing with it, and I can respond to feature requests before going RTM.  (Note that the EF Power Tools are also in Beta but will be folded into EF6 when it is released.)  So please let me know what you think and I’ll do my best to address any issues that come up.  Enjoy!

Posted in Technical | Tagged , , , | 18 Comments