The NHibernate Comparison of Entity Framework series
Part 1 A comparison on multiple database support in the Entity Framework and NHibernate O/RMs.Part 2 Last month I took the challenge of trying
to compare Entity Framework (EF4) and NHibernate (NH) in a hopefully unbiased and feature-driven way. In this article, I'll start looking into some programming features such as
lazy loading.
Part 3 This article is about fetch
plans-a recognized and common way for developers to instruct the O/RM about the structure of the SQL you desire.
Part 4 A Feature-driven Comparison of Entity Framework and NHibernate-2nd Level Caching
Part 5 A Feature-driven Comparison of Entity Framework and NHibernate - Self-tracking entities
Part 6 A Feature-driven Comparison of Entity Framework and NHibernate - Queries
Introduction
A common problem of multi-tiered architectures is exchanging data across tiers and especially between presentation and business. The ideal solution to this problem would be using ad hoc data transfer objects (DTO) so that you move around just the data you need to invoke necessary operations. A full DTO implementation, however, may really be painful when you start having hundreds of entities and use-cases to deal with.
Another aspect of multi-tiered architectures that fits in this scenario is the likely different representation of the data you have on the presentation and business layers. On the presentation layer you deal with data related to the user interface and use-cases. On the business layer, you tend to have entities that faithfully represent the entities in the problem's space. Unless you have quite simple, CRUD-oriented systems these two representations can hardly be the same. However, sometimes it happens that the UI representation can just be obtained composing together business entities with some other use-case specific properties.
When you send some business entities to the presentation and then you receive it back for updates, how can you be sure about the effective changes applied? Are you really interested in detecting changes? The reason for wanting to know the pending changes is writing a more optimized sequence of statements against the data store. As long as the business entity is single, getting to know the pending changes or not is not a big deal. When the business entity, however, is actually a graph of entities the benefits you can get from SQL optimization are potentially much more significant.
The typical solution to this problem consists in sending information about pending changes along with the data. For years, the DataSet class in ADO.NET just did so; and quite effectively. Once serialized, the DataSet could generate a Diffgram object with the list of updates, deletes, and insertions performed since last in-memory commit. Sent over the wire as plain XML, the DataSet once deserialized could easily expose its list of pending changes for the savvy business modules to employ optimized calls.
With O/RM tools, we mostly lose this feature. With O/RM tools in the Data Access Layer, either your presentation posts plain data that the business layer will process in the best possible way or, if an entity is posted, the O/RM will check its current state by fetching it again, determines the delta and then proceeds with optimized SQL calls. In this scenario, Entity Framework 4 comes up with a new approach that closely recalls the internal architecture of DataSets. The solution is based on self-tracking entities.
Introducing Self-tracking Entities
A self-tracking entity is a business entity capable of tracking changes being made as some client code manipulates the state the object itself. When exchanged across the boundaries of two interfacing tiers, it allows you to send and receive current state with detailed information of what has changed since the last significant step. Self-tracking entities are plain POCO business entities (plus change-tracking specific code) and are not as decoupled as DTOs. Self-tracking entities are not supported by NHibernate and have been introduced with Entity Framework 4.
In Entity Framework, as well as in NHibernate and other O/RM solutions, by default change tracking is implemented at the data context level. This means that any objects fetched by a given instance of the data context object are tracked correctly and constantly. However, this information gets lost as soon as the instance of the data context object goes out of scope. A common solution, but in some way discouraged by Microsoft, consists in caching the data context object and reusing it multiple times across requests at least until when the ongoing business transactions has terminated. In this way, with the same instance of the data context up and running you can re-attach objects and easily get the delta.
The recommended solution, however, is re-fetching the content of the business entity and then copying onto it the new posted values. In this way, the re-fetched instance within the new data context is marked as updated only for what has really changed meanwhile. The only drawback of this solution is the double roundtrip you need to deal with - one for fetching the object being updated and one to persist the object with its modified state. This approach is common to most O/RM tools.
Self-tracking Entities in Entity Framework
In Entity Framework 4, you create self-tracking entities from the designer. You first design your EDMX model and then, when it comes to choosing a code generation item, you pick up the one that gives you self-tracking entities. The source code of the entity classes is similar to that of POCO classes, except that a new change tracking engine is inserted in each. Here's the signature of an entity class:
The IObjectWithChangeTracker interface is also generated by the designer and just references to the change tracker engine, as below:
The ObjectChangeTracker class goes in a separate file generated by the designer. The class is the core of the change tracking engine and captures most of the change tracking work that needs to be done for self tracking entities. The setter method of properties on a self-tracking entity applies due changes and then notifies about just occurred changes. The notification is sent out through the INotifyPropertyChanged interface. Here's a code snippet:
Working with self-tracking entities is in no way different than working with plain POCO entities. It is important, however, that you tweak the Entity Framework class library project a bit so that you can obtain an assembly that only contains entities with no dependency on the Entity Framework assembly. This requires a little bit of magic with the .TT files you get when you add self-tracking entities from an EDMX model. For any model, the Entity Framework designer will generate a pair of TT files - yourModel.context.tt and yourModel.tt. The former file contains the data context object; the latter contains self-tracking entities. The file with the data context object must be moved to another class library project because it logically belongs to the DAL and because it requires a reference to the Entity Framework assemblies. To remain able to use the designer and further edit your EDMX file, however, you might want to just move a link to the yourModel.Context.tt file to the DAL project. In this way, in fact, any further change to the EDMX will correctly regenerate file from TT templates. To add an item to a project as a link, you just add it to the new project but click the Add As Link button from the Visual Studio dialog instead of the classic Add. (See Figure 1.)
Figure 1: Adding a project item as a link.

Having an entities-only assembly makes it so easy to share it with the presentation layer. The net effect is that you can now use the same entities on the client and the middle tier. The change tracking engine ensures that any change your client code performs on entities is tracked. Let's go through a typical scenario where all this machinery proves really helpful.
Imagine you have a use-case that entails you first query a bunch of objects and then display them to the client. The user interacts with these objects and then, after some changes have been made, he or she clicks a button to send data back. In this case, the modified entity travels back to server bringing its fresh content plus a detailed list of what has changed and why. This is really the same as the Diffgram bag carried by DataSet objects.
Once back on the server, the modified entities will likely be saved to the database. The problem that self-tracking entities address is optimizing this step by simply updating what has really changed. Now you should really from here the real scope of this feature - nice to have, good to use, but certainly not a must-have. As long as you are exchanging a single instance you don't see any relevant benefit from tracking changes - just some little overhead. Whether you pass back a Customer with a few modified fields, or a Customer that not having change tracking enabled looks entirely modified, does that really make a difference? The best you can get is a selective UPDATE command instead of an UPDATE command that touches on all columns. Better than nothing, you may say. Except that you won't even get this from Entity Framework, which seems unable to detect changes to individual fields! So what's the purpose of self-tracking entities? It saves you from unnecessary updates on unmodified entities when you move a large graph of objects across tiers.
The following code shows how you can use a brand new data context object to deal with a just received entity which will be able to work with the object using any change information the object carries:
The NHibernate Approach
In NHibernate, as well as in Entity Framework when not using self-tracking entities, dirty tracking works in the context of the same session. When you want to modify or insert an entity to the store you call the SaveOrUpdate method and it automatically matches changes and optimize data access operations. Dirty tracking, however, doesn't work with a detached entity like an entity the middle tier receives as posted by the presentation. In this case, either the detached entity comes with its own change log or you have to figure out what's different or just proceed with updates ignoring the delta. As mentioned, though, ignoring the delta may lead to severe performance consequences if the entity is actually the root of a large graph.
The common solution employed in NHibernate (and also in Entity Framework as an alternative to self-tracking entities) consists in fetching the entity from the data source and perform a manual merge of the changes. In NHibernate, this can be achieved with a single call.
The SaveOrUpdateCopy method originates a double roundtrip to the database to first re-read the content of the entity and then update it. In Entity Framework, to get the same results you must explicitly code yourself the two roundtrips which gives the false idea that NHibernate is, in this regard, far better!
Summary
Self-tracking entities is an Entity Framework-only solution, but the same problem it addresses is also solved (in a less automated way by NHibernate and the same Entity Framework). It mostly fills a gap for developers looking for an end-to-end .NET solution that brings the same ease of DataSets to the world of objects. Self-tracking entities are primarily aimed at handling entities within a graph rather than properties within an entity; but curiously the Entity Framework code requires some help to deal effectively with graphs as you may read here: http://blogs.msdn.com/b/adonet/archive/2010/06/02/working-with-sets-of-self-tracking-entities.aspx.
Self-tracking entities are optimized for WCF as data exchange technology and bind you to have .NET on the client and in the same version as the middle tier. So a self-tracking entity solution is not so open as you may have hoped. If it works for you, given a number of constraints, then you should use it. But I wouldn't say this is a key feature for an O/RM to have.
The NHibernate Comparison of Entity Framework series
Part 1 A comparison on multiple database support in the Entity Framework and NHibernate O/RMs.Part 2 Last month I took the challenge of trying
to compare Entity Framework (EF4) and NHibernate (NH) in a hopefully unbiased and feature-driven way. In this article, I'll start looking into some programming features such as
lazy loading.
Part 3 This article is about fetch
plans-a recognized and common way for developers to instruct the O/RM about the structure of the SQL you desire.
Part 4 A Feature-driven Comparison of Entity Framework and NHibernate-2nd Level Caching
Part 5 A Feature-driven Comparison of Entity Framework and NHibernate - Self-tracking entities
Part 6 A Feature-driven Comparison of Entity Framework and NHibernate - Queries
About Dino Esposito
 |
Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...
This author has published 53 articles on DotNetSlackers. View other articles or the complete profile here.
|
You might also be interested in the following related blog posts
New Entity Framework Feature CTP for VS2010 Beta 2
read more
Talking Points: ADO.NET Entity Framework
read more
More on Foreign Keys in EF
read more
Sneak Peek at the EntityDataSource Control
read more
Inheritance and the Entity Framework
read more
Exploring EntityKeys, Web Services and Serialization a little further
read more
LLBLGen Pro v2.0 released!
read more
DLinq: Playing with knives.
read more
|
|
Please login to rate or to leave a comment.