Entity Framework – Repositories, Fetching Strategies, Specification and Mapping – Using NFetchSpec for Role Driven Development. Parts 1 - 4
Over the course of the next month or so I will be posting a series on using a set of helper libraries which I refer to as NFetchSpec. I have taken the somewhat unusual course of creating this dedicated post that will act as an index of sorts for this series. Another reason for this aggregated index page is that the title of the series accurately reflects the intent of its content however not so much in a search friendly way and I want to make sure that it can be easily found by people who are interested in using Repositories, Fetching Strategies, Specifications and code only mapping.
NFetchSpec aims to provide a basis for using Repositories, Fetching Strategies, Specifications and Code Only mapping using a Role Driven methodology. Here is some example consumer code of NFetchSpec:
Listing 1.0
var customersStartWithA =
new Specification<IMakeCustomerPrefered>
(c => c.CompanyName.StartsWith(”A”));
var fetch = new FetchingStrategy<IMakeCustomerPrefered>(true);
fetch.AddIntentions(new IEagerFetchingIntention[]
{
EagerFetchingIntention.CreateInstance<IMakeCustomerPrefered,
ICollection<IOrder>>(c => c.Orders)
});
var repo = new CustomerBuyingStatusRepository();
var custs =
repo.Get<IMakeCustomerPrefered>(customersStartWithA, fetch);
foreach (var cust in custs)
{
cust.MakePrefered();
}
As described in Part 1.0, a role is an interface that describes a business or system event and can flag our intention; in the case of the code above, the intention is to make the Customer Preferred. Using NFetchSpec, this style of working (using roles) seeps into all aspects of the code. This is certainly not a requirement to use NFetchSpec and I will give some examples to the contrary as we get deeper into the series of posts, but it is the key reason for developing it. In Listing 1.0 we are using NFetchSpec to create a search predicate using a Specification instance, a Fetching Strategy to determine the most appropriate loading for the role and then finally using the Repository to get a Customer to make preferred. The API of NFetchSpec supports writing code like this, where each of the moving parts can be written in line together, however as mentioned in Part 1.0, one of the benefits of working in this role driven way is that we can use some IoC techniques to discover the correct Specifications and Fetching Strategies based on their implementing a given role, i.e, the interface that is specified to the Repositories .Get<TRole>() method. This is closer to the intended proposed usage:
Listing 2.0
var repo = new CustomerBuyingStatusRepository(); var custs = repo.Get<IMakeCustomerPrefered>();
The Code here in Listing 2.0 will instruct the NFetchSpec infrastructure to find a fetching strategy and Specification for this role when the overloaded version of the .Get<TRole>() method is called. This approach makes for an extremely flexible approach, swapping out the most appropriate component – if I don’t like the fetching strategy for a given role, I can simply replace it, facilitating just in time performance tuning (in the case of fetching) as we observe the system over time.
Here are the links to the posts in the series. You might notice that some of the links are not complete meaning that that post is yet to come. I will update this list as new posts make there way out.
Helping the Entity Framework Play it’s <Role> Part 1.0 (posted)
Helping the Entity Framework Play it’s <Role> Part 2.0 (posted)
Helping the Entity Framework Play it’s <Role> Part 3.0 (posted)
Helping the Entity Framework Play it’s <Role> Part 4.0 (posted)
All the code will be available on conclusion with the final post. Just one small thing before signing off, I really want to re-emphasise that it’s a really good idea to watch Udi present the ideas that lead me to attempt accommodating this approach for Entity Framework.
2 commentsHelping Entity Framework v4.0 play it’s <ROLE> – Part 1.0
With the Entity Framework version 4.0 just around the corner, I decided it was again time to address how to make the next version work in an explicit role based manner that also satisfies my wish to work with Domain Driven Design. This is the first of four posts that will detail a set of libraries that I currently have on my workbench, their aim is to aid working with the Entity Framework in the manner I shall describe here and throughout this series of posts. I hesitate to call it a Framework quite yet but it may well reach that point by the time of Entity Framework 4.0 RTM. In the meantime, I refer collectively to this set of libraries as NFetchSpec.
Programming to interfaces is not exactly a new idea right. We should all be familiar with the benefits of decoupling from a classes implementation. If this idea is new to you, here are a couple of links, the first is an interview with the venerable Erich Gamma and the other a video interview with WCF Uber Meister Juval Lowy who is also the author of .NET Components.
A couple years back I enjoyed attending Udi Dahan’s SOA and DDD course, during which I learnt about a lesser known benefit of using interfaces, using them to describe roles within the system. It’s just two weeks now until I have the opportunity to once again enjoy Udi’s SOA and DDD 5 day course and whilst I have been sitting on the code from this series of posts for some time now, it felt like now was a good opportunity to talk more about it. Before continuing with this post I strongly suggest you watch this video presentation Udi gave at QCon London in 2008, this will help provide a solid framing of the background that led up to my attempts to massage the Entity Framework into working in this fashion and ultimately making this series of posts.
As I sat in that classroom back in 2008 it was this simple line of code that really captured my attention, it was something of an aha moment.
Listing 1.0
1: using (ISession s = ORM.OpenSession())
2: using (ITransaction tx = s.BeginTransaction())
3: {
4: IMakeCustomerPreferred c = s.Get<IMakeCustomerPreferred>(id);
5: c.MakePreferred();
6: tx.Commit();
7: }
The line of code to note here is on line 4:, by being explicit and letting the infrastructure code (NHibernate in this case) know what our intention is by specify a role (the IMakeCustomerPreferred interface), we can do some interesting things! We can:
- Make use IoC and service locate the appropriate Fetching Strategy, that is one designed to best suit the role of making a customer preferred. In this example, we want to eagerly fetch all the orders and order lines to make the appropriate adjustments.
- Return an appropriately mapped concrete implementation for the role of IMakeCustomerPreferred. Entity Framework 4.0 code only mapping has made this a possibility.
By being very explicit with the role I can let NFetchSpec do the lifting in finding the most appropriate entities and fetching strategy to load. For performance reasons alone I may have more than one combination. Bear in mind the code in listing 1.0 is part of a service layer and the concrete entity implementing IMakeCustomerPreferred contains a business operation to make a customer preferred – which may involve discounting current orders on hand for example. The equivalent of this block of code for the Entity Framework could indeed abstract away all the following code:
static void Main(string[] args) { var builder = new ContextBuilder<ObjectContext>(); builder.Configurations.Add(new CustomerMapping()); builder.Configurations.Add(new OrderMapping()); builder.RegisterSet<Customer>(“Customers”); builder.RegisterSet<Order>(“Orders”); var cnxString = “Server=BOOMER\\BOOM09;Database=CodeOnly;”+ “Trusted_Connection=True;MultipleActiveResultSets=true”; var connection = new SqlConnection(cnxString); var context = builder.Create(connection); var custs = context.CreateObjectSet<Customer>(); context.Connection.Close(); context.ContextOptions.LazyLoadingEnabled = true; foreach (var cust in custs) { Console.WriteLine(cust.FirstName + ” has {0} orders”, cust.Orders.Count()); } Console.ReadLine(); }
Some of the accompanying Mapping Code
public class CustomerMapping : EntityConfiguration<Customer> { public CustomerMapping() { Property(c => c.CustomerId).IsIdentity(); Property(c => c.FirstName).HasMaxLength(50).IsRequired(); Property(c => c.LastName).HasMaxLength(50).IsRequired(); Relationship(c => c.Orders).IsOptional(); Relationship(c => c.Orders).FromProperty(o => o.Customer); } } public class OrderMapping : EntityConfiguration<Order> { public OrderMapping() { Property(o => o.OrderId).IsIdentity(); Relationship(o => o.Customer).IsRequired(); Relationship(o => o.Customer).IsRequired().FromProperty(c => c.Orders); } }
Before we delve into NFetchSpec deeply in the following posts, let’s take a quick look at some typical consumer code:
Notice also that there is no orthogonal technology bleed in this code, my ORM technology knows nothing of my business entities and my business entities know nothing of my ORM technology. The CustomerBuyingStatusRepository class is a specialised IRepository and through IoC we get the right ObjectContext, the correct mapping, the type of Customer entity that we make preferred and with the correct eager loading to bring across the orders and order lines in one go.
If you want to gain a better understanding of working in this style then I really do urge you to go and watch this video and then return here to continue and follow this series of posts.
If your not sure about Fetching strategies you can get up to speed by reading these links. They will also be useful in preparing the ground for this series of post which relates only to Entity Framework 4.0:
- Fetching Strategies in Entity Framework 4.0 (an early look)
- 11 part series on Repositories, Fetching Strategies and Specifications (EF 1.0)
- A slimmed down Fetching Strategy for out of the box Entity Framework code.
This series of posts (probably 4 in total) will cover the same aspects that were covered in the 11 part series on Repositories, Fetching Strategies and Specifications, however we will look at how the story around most of those elements in NFetchSpec have been improved by virtue of some of the new excellent features in Entity Framework 4.0, such as POCO Entity support and Code Only Mapping which will not feature entirely in 4.0 but sometime (hopefully) shortly after. In part 2.0 we will begin to deep dive into NFetchSpec and I will make the code available for download.
8 commentsNServiceBus - Entity Framework Saga Persister
In my last post I demonstrated a LINQ To SQL Saga Persister for NServiceBus and promised to follow it up with a similar dose of medicine - an Entity Framework Persister, specifically demonstrated for Version 1.0 of the Entity Framework.
Obviously after two previous posts on the LINQ To SQL Persister I am not going to cover the same ground in terms of explaining the various pieces of the puzzle, rather what I would like to do is simply point out some of the differences in the two implementations and note my observations.
As we did previously, let’s start out with the configuration code that uses the Entity Framework Persister.
static void Main() { LogManager.GetLogger("hello").Debug("Order Started."); try { const string dbConnectionString = "metadata=..\\..\\Mapping\\OrderSagaDataModel.csdl|..\\..\\Mapping\\"+ "OrderSagaDataModel.ssdl|..\\..\\Mapping\\OrderSagaDataModel."+ "msl;provider=System.Data.SqlClient;provider connection "+ "string=\"Data Source=BOOMER\\BOOM09;Initial Catalog=Sagas;"+ "Integrated Security=True;MultipleActiveResultSets=True\""; var sessionFactory = EntityFrameworkSessionFactory .Configure(dbConnectionString, typeof(OrderSagaData), "OrderSagaDataLines"); NServiceBus.Configure.With() .CastleWindsorBuilder( (cfg => { cfg.ConfigureComponent<OrderSagaFinder> (ComponentCallModelEnum.Singlecall) .SessionFactory = sessionFactory; })) .XmlSerializer() .MsmqTransport() .IsTransactional(true) .PurgeOnStartup(true) .IsolationLevel(IsolationLevel.RepeatableRead) .DbSubscriptionStorage() .Table("Subscriptions") .SubscriberEndpointColumnName("SubscriberEndpoint") .MessageTypeColumnName("MessageType") .Sagas() .EntityFrameworkSagaPersister<OrderSagaData>(sessionFactory) .UnicastBus() .ImpersonateSender(false) .LoadMessageHandlers( First<GridInterceptingMessageHandler> .Then<SagaMessageHandler>() ) .CreateBus() .Start(); } catch (Exception e) { LogManager.GetLogger("hello").Fatal("Exiting", e); } Console.Read(); }
Kissing Cousins?
So what are the main differences between the LINQ To SQL and Entity Framework Persisters?
The Session Factory
- Manages an ObjectContext vs. DataContext
- Manages a string for the ObjectQuery<T>.Includes() argument to achieve eager fetching of the entire Saga’s state graph.
- The Connection string includes the details and path to the mapping files.
- No TextWriter for logging.
- Requires to know the Type of Saga Entity to effect reading the mapping files meta data to ascertain the Default Container Name for the ObjectContext.
The Saga Finder
public OrderSagaData FindBy(string purchaseOrderNumber, Guid partnerId) { SessionFactory.GetSession().DefaultContainerName = "SagasEntities"; var sagaData = SessionFactory.GetSession() .CreateQuery<OrderSagaData>("[OrderSagaData]") .Where(o => o.PurchaseOrderNumber == purchaseOrderNumber && o.PartnerId == partnerId); foreach(var include in SessionFactory.IncludeInFetching) { sagaData = ((ObjectQuery<OrderSagaData>) sagaData).Include(include); } return sagaData.FirstOrDefault(); }
It’s almost identical to the LINQ To SQL finder with the following differences:
- Eager Fetching via the .Include method.
- Requires the DefaultContainerName which is available from the MetaDataWorkspace of an EntityConnection – this is specified in the mapping files.
Other Stuff
- Isolation Level Defaults in the Entity Framework were by default Serializable and LINQ To SQL varied according the the operation in use. Setting the isolation level when configuring the bus settles this for both Persisters.
- LINQ To SQL Persister requires cascade delete to be set in the database to clean up the entire Saga.
- Entity Framework Version 1.0 of course does not support POCO and LINQ To SQL for the most part does.
- I don’t like the way Entity Framework forces me to have persistence code bleed into my Saga Entities – notice how the OrderSagaData class made its way from the OrderService to the OrderService.Persistence project so it could sit alongside the Entity Data Model.
The Last Word
Just as with the LINQ To SQL Persister, this one needs to be merged via a batch file in the build folder and the subsequent single DLL is all you will need to use the this Persister.
I have made the entire code for the Entity Framework Saga Persister available from this link. I shall finish off the series by following up shortly by demonstrating how to use the Persister with the next version of the Entity Framework (4.0), which thankfully does support POCO.
7 comments







