Entity Framework Week Part 2: Conventions and Fluent Mappings

1

This is the second in a series of five posts recounting my experiences using Entity Framework Code-First to replace ADO.NET and stored procedures in a client’s existing application. The introductory post in the series is here.


As mentioned in yesterday’s post, I was attempting to use Entity Framework Code-First CTP5 to map an existing domain model to an existing database schema. Fortunately the project was in its infancy and there was a high degree of cohesion between the two models. I therefore didn’t anticipate too many difficulties ahead – the occasional naming discrepancy to resolve, and table-per-hierarchy mappings that would need their discriminators specifying – nothing too complicated really. I hoped to make as few changes as possible to either the database schema or domain model.

Entity Framework Code-First uses a set of conventions to “discover” the mappings from domain objects to database. This is broadly analogous to James Gregory’s Fluent NHibernate AutoMapping functionality.

As with Fluent NHibernate, it is possible to add custom conventions, and to manually override mappings for specific properties which deviate from the conventions. It is also possible to remove existing conventions.

All of these modifications to the model mappings are affected by overriding the virtual OnModelCreating method in our concrete implementation of DbContext. I was initially worried about the sheer volume of code that might be included in this method, and was relieved to discover that mapping overrides related to particular entities can be separated out into the constructor of generic implementations of EntityTypeConfiguration, not unlike the generic ClassMap in Fluent NHibernate.

Custom Conventions

In the domain model I was working with, all entities were derived from an abstract base Entity class which defined an integer Id property. By contrast, the primary keys on the database tables were all prefixed with the name of the table/entity. Neither of these situations are ideal, but nor are they all that unusual, and I sought a way of “teaching” this convention to our custom EF context.

It took me some time to discover that custom conventions are even possible in CTP5, and I had initially resigned myself to manually overriding the names of each and every primary key property. It was only through stumbling upon this post on the ADO.NET team blog that I found what I was looking for. Note that this post does include the caveat “There are a number of rough edges and the API surface is likely to change”.

My first impression is that custom Entity Framework conventions could turn out to be far more powerful than those offered by Fluent NHibernate, but they are also trickier to develop, requiring an understanding of the valid options for the two generic parameters that IConfigurationConvention can take, and what actions should be taken by the custom convention.

Still, after a little trial and error I was able to write the custom primary key convention that I required:

public class MyAppPrimaryKeyConvention : IConfigurationConvention<PropertyInfo, PrimitivePropertyConfiguration>
{
    public void Apply(PropertyInfo memberInfo, Func<PrimitivePropertyConfiguration>; configuration)
    {
        if (memberInfo.Name == "Id")
        {
            // We need to avoid overriding concrete class mapped using TPH.
            if (memberInfo.ReflectedType.IsSubclassOf(typeof(ProductFeature)) ||
memberInfo.ReflectedType.IsSubclassOf(typeof(ProductInsert)))
            {
                return;
            }
            configuration().ColumnName = string.Format("{0}Id", memberInfo.ReflectedType.Name);
        }
    }
}

I was disappointed that I had to insert a guard clause to ignore this convention for the concrete subclasses of hierarchies that are mapped using table-per-hierarchy (i.e. ProductFeature and ProductInsert). Given time I would hope to find a generic way of achieving this convention that doesn’t require hardcoded references to specific Domain objects from within the convention definition.

Compare and contrast with the equivalent code for Fluent NHibernate:

public class MyAppPrimaryKeyConvention : IIdConvention
{
    public void Apply(IIdentityInstance instance)
    {
        instance.Column(string.Format("{0}Id", instance.EntityType.Name));
    }
}

Updated:

Since I wrote the section above, the ADO.NET team have announced details of the forthcoming Entity Framework 4.1 Release Candidate, which removes this ability add conventions:

“This was a very painful decision but we have decided to remove the ability to add custom conventions for our first RC/RTW. It has become apparent we need to do some work to improve the usability of this feature and unfortunately we couldn’t find time in the schedule to do this and get quality up the required level. You will still be able to remove our default conventions in RC/RTW.”

For what it’s worth, I think this was the right convention to make. A lack of “pluggable” conventions is slightly disappointing, but it can easily be worked around by making the appropriate overrides with the fluent mappings. Better to hold off an nail an API that’s both powerful and usable than go too soon with something that’s liable to confuse and confound.

Removal of Default Conventions

Another nice feature described in the Pluggable Conventions blog post is the ability to remove some of the default conventions, which I immediately put to good use by disabling the default PluralizingTableNameConvention:

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

(I mean, for goodness sake, who in their right mind pluralizes table names anyway? Yes, it’s very impressive that this library knows that the plural of “goose” is “geese”, but it would be more beneficial if that were an extension method on System.String in the BCL rather than being buried in the bowels of System.Data.Entity.Design. Then perhaps the ADO.NET team could be left to get on with developing something more useful, like second-level caching? Sorry, rant over…)

Fluent Mapping API

Most manual tweaks to the model are fairly straightforward to perform, and there are a good set of examples in this post on the ADO.NET team blog.

I did encounter some difficulty with the mapping of one-to-many relationships, which felt quite cumbersome to perform in comparison to the brevity of Fluent NHibernate’s API. Here’s how you’d rename a foreign key on a unidirectional one-to-many relationship in Fluent NHibernate:

References(x => x.AudioFormat).Column("AudioFormat");

Whilst in Entity Framework code-first, the equivalent is:

HasOptional(x => x.AudioFormat)
.WithMany()
.IsIndependent()
.Map(m => m.MapKey(a => a.Id, "AudioFormat"));

To be fair, I think part of this clumsiness arises because Entity Framework is allowing us to define both ends of a bidirectional relationship in a single place, whereas NHibernate requires us to define each end separately. It’s just unfortunate that in unidirectional situations like this example we end up with the WithMany().IsIndependent() noise in the middle of the syntax.

Having learned the odd syntax required to rename these one-to-many foreign keys, I then wasted an inordinate amount of time trying to make this actually work. Many of my waking hours were blighted by an InvalidOperationException (“Sequence contains more than one matching element”) originating from deep within the framework. A quick ferret around on Stack Overflow revealed that I was not the only person currently banging his or her head on this particular brick wall:

Eventually Diego Mijelshon figured out what was amiss. It seems the mapping failure was due to the Id property being defined in a base class rather than on the concrete class being mapped. Whether this is intentional behaviour or a bug in the CTP5, I’m not sure, but I worked around this issue by modifying the domain model and ditching the hierarchy of base classes altogether, leaving the Id and other common properties defined only on interfaces. Ayende would be pleased.


Two days into my adventure, and my database and domain model were happily mapped. In part three I’ll look at some of the issues I encountered at runtime, which necessitated further tweaks to the domain model and database.

Entity Framework Week Part 1: Introduction, Configuration and Initialization

2

In February 2011 I found myself doing some contract development work in a team that was still doing data access using raw ADO.NET and stored procedures. Being the NHibernate fanboy that I am, I naturally attempted to persuade them of the benefits of moving over to NH, even going so far as to develop (in my own time) an NH-powered version of their application.

My efforts were partially successful. The team were sold on the idea of using an ORM, but wanted me to develop a second proof of concept using Microsoft ADO.NET Entity Framework rather than NHibernate. This prompted much mirth amongst my FaceBook friends.

FaceBook

I decided to throw myself into the task, and use this opportunity to spend some time getting to grips with Entity Framework in a real-life scenario for a couple of weeks. I figured that in the best-case scenario, I would learn to love EF even more than NH, and bolster my CV. Worst case, I’d hate it but would be moving on to a new contract shortly anyway, so wouldn’t have to live with it for too long. And of course I was getting paid for the experience either way, so what’s not to like?!

A couple of friends rightly suggested that I ought to blog about my experiences, so here we go.

This series of five blog posts details the thoughts and experiences I encountered during my week-long adventure with Entity Framework. It isn’t an EF walkthrough, nor is it a comprehensive EF-vs-NH feature comparison (the web is littered with those).

  1. Introduction, Configuration and Initialization
  2. Conventions and Fluent Mappings
  3. Runtime Issues Encountered
  4. Features and Further Investigations
  5. Concluding Thoughts

Choosing Code-First

When last I had a quick play with Entity Framework in the summer of 2008, it was very IDE and database-driven – the development process entailed dragging tables onto a designer surface which generated partial classes to represent objects, etc. Yuk! The lack of support for a domain-driven, persistence-ignorant approach was a real turn-off for me, prompting me to add my name to the list of signatories on the infamous ADO.NET Entity Framework Vote of No Confidence.

It was therefore a relief to discover that Entity Framework now supports a “Code-First” development paradigm, whereby EF can be used like a traditional ORM to fluently map an existing domain model to an existing database. At the time, this was still available only as a Community Technology Preview (CTP5), but given my remit was to introduce EF to an existing solution, it was a no-brainer to choose this option for the proof of concept, even though this would potentially leave me exposed to bugs and breaking API changes.

Configuration

Configuring Entity Framework seemed a lot easier than the equivalent procedure with NHibernate, filled as it is with esoteric options which can often be somewhat perplexing to NH newbies. With EF, the walkthroughs told me that essentially, all I needed to do was create a subclass of DbContext and Bob would be my mother’s brother. They were right. If anything, it was all too easy, and I wondered how and where I would get the option to configure details such as the second-level cache provider and ADO batch size.

I made use of a constructor overload on DbContext which takes a string parameter called nameOrConnectionString. Initially I attempted to pass into this parameter a connection string obtained from the app.config file using System.Configuration.ConfigurationManager, but this led to error messages along the lines of

“Unable to determine the provider name for connection of type ‘System.Data.SqlClient.SqlConnection’”

It seems that the connection strings used by Entity Framework are not the common or garden connection strings that we know and love, but instead special EF connection strings. Fortunately, a simple remedy to this issue was to instead just pass the connection string name into the exact same parameter. See this forum post for more details.

Database Initializer Strategies

Entity Profiler revealed that Entity Framework was unsuccessfully attempting to access a nonexistent database table called dbo.EdmMetadata. A little light Googling revealed that this is used by Entity Framework to store (perhaps unsurprisingly) metadata about the Entity Data Model. Why does it do this? Presumably so that it can decide at application start up whether code changes to the model require it to automagically make associated changes to the database schema. Some Summer 2010 blog posts from Scotts Guthrie and Hanselman show off the ability of Entity Framework to automatically create and update databases in response to model changes.

Now, this is all very clever and might be fine for hobbyist websites, integration tests and those quintessential “Look – no code!” TechEd presentations, but in an enterprise scenario it’s liable to cause acute apoplexy in DBAs.

Fortunately we can opt to suppress this crazy behaviour altogether by passing a null strategy into DbDatabase.SetInitializer, thus:

DbDatabase.SetInitializer<MyAppContext>(null);

That was day one over – I was officially up and running in the brave new (to me) world of Entity Framework. In part two of this series I’ll take a look at the mapping tweaks I had to make to successfully map our existing domain model to our existing database.

What I’ve Been Listening To In 2010

0

Courtesy of Last.fm, here’s what I’ve been mostly listening to during the last year:

Artists:

  1. Manic Street Preachers
  2. The Divine Comedy
  3. Arcade Fire
  4. Belle and Sebastian
  5. British Sea Power
  6. R.E.M.
  7. Hole
  8. Morrissey
  9. Florence and The Machine
  10. The Like

Albums:

  1. Arcade Fire – The Suburbs
  2. Belle and Sebastian – Write About Love
  3. Manic Street Preachers – Postcards From A Young Man
  4. Hole – Nobody’s Daughter
  5. The Divine Comedy – Victory For The Comic Muse
  6. Florence and The Machine – Lungs
  7. The Divine Comedy – Bang Goes The Knighthood
  8. The Like – Release Me
  9. The Pretty Reckless – Light Me Up
  10. The Temper Trap – Conditions

Tracks:

  1. The Temper Trap – Down River
  2. Florence and The Machine – Cosmic Love
  3. The New Pornographers – Sing Me Spanish Techno
  4. The Divine Comedy – At The Indie Disco
  5. Jack – Lolita Elle
  6. Foo Fighters – Wheels
  7. Miley Cyrus – Party In The U.S.A.
  8. Nada Surf – Enjoy The Silence
  9. Lena – Satellite
  10. The New Pornographers – Graceland

Most-Read Posts 2010

0

Courtesy of Google Analytics, here are my top 10 most-read blog posts from 2010:

Posts published in 2010 only:

  1. Enterprise Integration Anti-Patterns #1 – The Shared Database (08 November).
  2. WCF – NHibernate Unit Of Work Endpoint Behavior (09 April).
  3. MVC – Where To Put Business Logic? (03 November).
  4. Enterprise Integration Anti-Patterns #2 – Shared Assemblies (01 December).
  5. WCF – Logging Before and After Operation Invocation (09 April).
  6. An MVC Gotcha and the PRG Pattern (09 April).
  7. WCF – Global Exception Handling (09 April).
  8. NHibernate and Mapping Aggregates (25 November).
  9. On the Relative Prices of Petrol and Diesel (03 April).
  10. VS2010 – MyClassInitialize Has Wrong Signature (17 February).

All Posts:

  1. Team Foundation Server – Sharing Binaries and Class Libraries across Multiple Projects (17 March 2007, Last Year #1).
  2. A Serializable KeyValuePair Class (17 September 2006, Last Year #2).
  3. Spot The Misleading Graph (19 February 2007, Last Year #4).
  4. Is My String Empty? Some C# Performance Metrics (30 July 2004, Last Year #3).
  5. Postcode Validation (23 May 2007, Last Year #5).
  6. MSB3247 – Dependent Assembly Conflicts (04 December 2008, Last Year #6).
  7. Enterprise Integration Anti-Patterns #1 – The Shared Database (08 November 2010).
  8. TFS: Using Alternative Diff/Merge Tools (19 May 2009, Last Year #14).
  9. WCF – NHibernate Unit Of Work Endpoint Behavior (09 April 2010).
  10. MVC – Where To Put Business Logic? (03 November 2010).

Available For Work Again

2

As 2010 heads inexorably towards its festive conclusion, so too does my current contract at NHS Choices. I’ll be looking for a shiny new contract to get my teeth into from Wednesday 22nd December.

Want some evidence that the great British taxpayer has been getting VFM from yours truly during my time providing services to the NHS? Check out this comment from Development Manager Nick Porthouse:

"Ian worked on a particularly troublesome project for me for eight months at NHS Choices without complaint. His development skills and knowledge are exemplary and his NHibernate knowledge is second to none. He worked well with all the members of the team and helped me to introduce pair programming and push the test driven development agenda. I will employ Ian whenever I have the chance.”

Do you have any troublesome .NET projects (or, if you insist, even non-troublesome ones) that could benefit from my assistance? If so, give me a call on 07901 828483 or drop me a line at ian@iannelsonsystems.com .

Enterprise Integration Anti-Patterns #2 – Shared Assemblies

1

Having slain the beast that is Shared Database, the next dragon to appear on my Enterprise Integration horizon is Shared Assemblies. That is, the suggestion that Application A can leverage the functionality of Application B by simply adding references to B’s DLLs. After all, this potential for reuse is why we put our code in reusable assemblies in the first place, isn’t it..?!

iStock_000012931845XSmall

Well, no. Actually we usually break our application apart into assemblies to create a maintainable and testable architecture. An assembly is a coarse-grained unit of encapsulated functionality in that architecture; the fact that it is the smallest deployable unit in the .NET world is not necessarily an indication that we intend or desire our assemblies to be shared with other applications.

In my experience, sharing assemblies works only when they have been developed with this intention in mind. It’s feasible to share DLLs that contain discrete chunks of easily-encapsulated functionality that have no need for external dependencies (hasn’t every dev shop got a “common” or “utilities” library hanging around somewhere?!) but it’s quite another matter to start taking a wholesale dependency on the guts of another application.

So, before you try the shared assemblies approach to enterprise integration, here are a few things to consider:

Is It Even Possible?

Firstly, this approach makes the assumption that the application to be referenced has been developed such that all the logic to be invoked exists in the assemblies. If the application wasn’t originally developed with the intention of being shared in this way, there’s every possibility that some pertinent logic has instead been located in the front-end (e.g. the “Magic Pushbutton” anti-pattern that was so prevalent in ASP.NET Web Forms development), or even client-side scripts.

Love Me, Love My Dependencies…

All applications have dependencies of one kind or another. If you’re lucky, this will just be the .NET Framework, and if you’re especially lucky it will be the same version that is used by the consuming application.

More likely, the application being referenced will depend on a whole bunch of third-party DLLs, and now they’ve suddenly become your dependencies, too! If your dev shop is anything like the places I’ve worked, each application will depend on various different versions of the NHibernate and Castle stacks and their associated dependencies. Good luck managing all those references while retaining your sanity.

Applications are more than just DLLs

The average enterprise application is more than just a bunch of assemblies that can be referenced independently. They also tend to rely on configuration settings, external resources (e.g. databases), and a whole bunch of stuff triggered at application start-up time such as the configuration of an IoC container, logging, ORM, etc. The handling of authentication and authorization might also need rethinking before assembly sharing becomes a viable option.

Maintaining the Combined Suite of Applications

As I said in my previous post on this topic, maintainability is a particular bugbear of mine as a developer, and sharing assemblies across multiple applications doesn’t help matters one iota.

Unless you work with unbearably large solutions containing every project in your suite of applications, it’s difficult to know the wider impact that modifications will have, and to avoid making breaking changes. For sure, it’s possible to run automated builds of all applications when shared code is changed (I blogged about one method of achieving this with the first version of Team Foundation Server some years ago before I came to the conclusion that this is A Bad Idea) but by then the hard work has been done, the code checked in and the damage done.

Arguably, sharing assemblies puts developers in an even stickier situation than sharing databases – at least with that anti-pattern the entanglement is limited to one particular layer of the architecture which can be largely ignored much of the time. But when assemblies are shared, the developers must always be considering whether their apparently innocent modifications will have an impact on some other application. Meaningful refactoring becomes impossible, and the software eventually falls into disrepair.

iStock_000004248715XSmall

In Conclusion…

When all is said and done, there are only two realistic patterns for sharing functionality between enterprise applications – remote procedure invocation and messaging. Both serve to decouple the applications, and both are easy to achieve with popular technologies on the .NET stack such as WCF, OpenRasta and MassTransit.

There’s an abundance of resources out there detailing how to create effective service-oriented architectures, the obvious canonical reference tome being Hohpe and Woolf’s Enterprise Integration Patterns. I also highly recommend Michael Nygard’s Release It! for an entertaining overview of some of the problems that can be encountered when you start taking dependencies on remote services, and useful patterns for ensuring your application remains responsive at all times.

My preferred technology stack for application integration remains WCF, and in a future blog post I’ll outline some tips I’ve learned through trial and error for developing and consuming effective and maintainable WCF services.

NHibernate and Mapping Aggregates

2

A few days ago a friend emailed me the following question regarding NHibernate mappings for a solution he’s currently developing:

“I have an idea entity that has a collection of comment entities and I need to get the comment count for each idea. I made a massive mistake at the beginning by calling idea.Comments.Count (even worse, I did it in the view!), which due to the collection being lazy-loaded caused about 10 database calls so performance was sluggish even with second level cache.  I was therefore wondering how you would do it – would you use HQL and use Comments.size or would you do something differently?”

Now, I’ve been pretty busy recently, so before I had opportunity to respond properly, he sent this follow-up:

"After looking for a solution for getting a Comment count back for each Idea, I found using the Nhibernate Formula method does the job – just wanting to make sure I was on the right track in terms of performance etc.  My mapping class is as follows:"

public class IdeaMap : ClassMap<Idea>
{
    public IdeaMap()
    {
        Id(x => x.Id)
            .Column("ID")
            .GeneratedBy.Identity();

        Map(x => x.Summary).Not.Nullable();
        Map(x => x.Description).WithMaxSize().Not.Nullable();
        Map(x => x.Created).Not.Nullable();
        Map(x => x.LastStatusChange).Not.Nullable();
        Map(x => x.Visible).Not.Nullable();
        Map(x => x.Status).Not.Nullable();

        Map(x => x.CommentCount)
            .Formula("(select count(*) from Comment c where c.IdeaId = ID)");

        HasMany(x => x.Votes).KeyColumn("IdeaId")
            .Inverse().Cascade.AllDeleteOrphan();

        HasMany(x => x.Comments).KeyColumn("IdeaId")
            .Cascade.All();

        References(x => x.Category).Column("CategoryId")
            .Not.Nullable();

        References(x => x.CreatedBy).Column("UserId")
            .Not.Nullable();

        Cache.ReadWrite();
    }
}

I considered this for a while, and sent the following suggestions:

“I’m glad to hear you resolved your SELECT N+1 problem but to be honest, I’m not a big fan of using formulas in NH mappings if at all possible, for the following reasons:

  1. I try to minimize my use of strings (and especially SQL) so as to make refactorings easier, and lessen the potential for runtime exceptions.
  2. The default NH behaviour will be to evaluate that formula every time an Idea entity is loaded, which might not be desirable and could negatively impact on performance when loading your idea entities. I’m not sure if the recently-added Lazy Properties feature of NH can be applied to these derived properties; if so then that could be used to negate this argument.
  3. I try to avoid putting logic (however simple) in the OR mapping layer, as future developers are unlikely to expect to find it there! I like to reduce the element of surprise in my solutions, and put such logic in the domain layer. I think logic in the OR layer limits options going forward – for example if you subsequently decide all comments have to be moderated, does the CommentCount formula have to be modified to exclude comments awaiting moderation..?

So, what would I do? Here are two options, depending on how often you’re using the CommentCount property:

If you’re only using the CommentCount occasionally and only along with a subset of the other properties from Idea, then I would write a specific query returning a projection of the required properties, including this CommentCount aggregate.

I’ve done this in the past where I had a requirement to populate a drop-down list with user names and the number of open work items assigned to each user, for example. I didn’t want or need to maintain an ActiveWorkItemCount property on the user object, I just wanted to do the calculation in one place (incidentally, LINQ made this a doddle).

Conversely, if the CommentCount property is something you’re going to be referencing frequently, then I would denormalise the database and add a CommentCount field to the Idea table. This presumes that you’re in a position to enforce the constraint that new Comments are only added to Ideas through your application (and as you know from my recent blog post, I am very fond of this kind of constraint!). This approach should give the best performance and flexibility, at the expense of irking normalisation fascists.

Typically this would be done by creating AddComment and RemoveComment helper methods on the Idea entity, which can maintain a bidirectional relationship between Idea and Comment in addition to incrementing or decrementing CommentCount accordingly.

This approach will give the best performance, and keeps the logic where it belongs (and where it can be easily extended and tested, as in my earlier hypothetical comment moderation example).

For a good example of code to maintain bidirectional one-to-many class relationships with NHibernate, see pages 39-43 of NHibernate 3.0 Cookbook.

Hope this helps. As ever, it’s just my opinion, but these two techniques have worked well for me.”

What do you think? Are there any other approaches worth considering?

Enterprise Integration Anti-Patterns #1 – The Shared Database

3

So, I was in the office at a client site, walking back to my desk after grabbing a quick coffee, when a developer on a sister product to my current project grabbed me and asked (I paraphrase somewhat):

“Hey, Ian – [my app] needs to retrieve [small piece of data] from [your app], so I’ve stuck a stored proc in [your database], OK?”

I felt quite violated. My poor app, what had it done to deserve this despicable treatment?

Before I start my rant about the downsides of directly accessing application databases in this way, let me first try to enumerate the benefits of such an approach. I can think of three:

  1. It’s a quick solution to develop (at least initially).
  2. The technical concepts involved are well understood by the vast majority of developers and other team members.
  3. The functionality is encapsulated in one place, i.e. the stored proc, which is at least preferable to allowing the execution of ad-hoc SQL.

But despite this being seen as a quick-win, I think allowing application databases to be shared in this way is almost always a bad idea in the medium to long term.

As a developer, one of my primary goals is to create systems that are easy to maintain and enhance, in anticipation of the inevitable future change requests that will put food on my children’s plates. As well as making life easier for yourself, this approach is also common courtesy to the programmers that maintain the system after you’ve left. As the saying goes, “always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live” – I think that’s good advice to heed for all developers who have an interest in building their reputation in our small and incestuous industry.

When we begin down the slippery slope of forcing a single database to serve the needs of multiple disparate consuming systems, we make a rod for our own backs. Any planned changes to the database to meet new requirements in the primary application need to consider the needs of the parasitic applications that care little for your ability to respond to change as long as they continue working. In our particular scenario, it’s worth highlighting that “my” application is using NHibernate as an ORM layer, so until this invasion we have been able to perform database schema refactorings with relative impunity. No longer – now we have to consider and potentially maintain someone else’s stored procedure when making changes.

Sure, at the start it’s “just a stored proc”, and the maintenance overhead is relatively low. But like the proverbial broken window, allowing that first chink in your carefully-crafted layered application architecture sets a dangerous precedent. If it goes unchecked, it may be seen as a valid pattern to be emulated by future developers, until the database schema ossifies and becomes almost impossible to change as it struggles to meet the requirements of multiple consuming applications.

If you think I’m scaremongering or labouring a point here I would urge you to spend some time hanging out on the NHibernate and Fluent NHibernate mailing lists. It won’t be long before you see messages that describe complex and intractable mapping problems and mention the caveat “I’m not allowed to change the database”.

Aside from the maintainability issue (which is my major gripe), the end result of this quick-and-dirty approach also leads to a poorer-quality solution which may struggle to meet nonfunctional requirements. Direct database access from external applications is a crude, low-level solution to a common problem. All the hard work done in creating a layered architecture with DAOs, business logic layer etcetera is swept aside by some other cowboy app which says “screw all that, gimme the data”. Any considerations that may have been given to concerns such as caching and application-level security go out of the window. The potential for locks and even deadlocks on the shared database is increased.

If you have the smallest shred of dignity and self-respect on behalf of your application, then please – don’t let its nether regions be exposed to all and sundry.

MVC – Where To Put Business Logic?

6

I just had an email from a friend asking where business logic should go when using MVC – the controller or the model.

I thought I’d share my reply:

I think asking whether the business logic should go in the Model or the Controller is a false dichotomy. There are different kinds of business logic, and there’s also the possibility of putting it somewhere else entirely.

Much business logic does indeed belong in the model, particularly stuff like encapsulating calculations and projections, adding meaning to raw data properties, and ensuring domain objects are maintained in a valid state. I see this as the traditional side of OO design – encapsulating logic and restricting accessibility.

Then at a higher level we have logic which deals with interactions between objects, which are essentially transactions and generally map to business use cases. I contend that this kind of logic belongs in a separate "service" layer. The interfaces in that service layer can then be referenced by the controllers, which are rendered super-skinny and free of any complex "business logic". The same service layer classes can be invoked from other front ends – Web Forms, Win Forms, WCF services, console apps, etc.

As a further aside, I’d recommend use of a view model or DTOs wherever possible rather than exposing the domain model objects up to the views / forms / console / service contracts etc. This encapsulates the domain model and increases the maintainability of the domain model.

What do you think?

Testing IoC Registrations

0

When I first started writing automated unit tests for my code, I remember getting carried away writing lots of tiny little tests, each with a single Assert. It felt good initially to see all those green ticks, but rapidly became a maintenance headache, and I am now happier having fewer less-brittle tests that do more.

I think it’s great when tools like AutoMapper provide powerful methods like…

AutoMapper.Mapper.AssertConfigurationIsValid();

…allowing me to test large swathes of the system configuration with a single, stable test.

I wanted to write a similar test to check that all the necessary system dependencies for my MVC application could be resolved by the IoC container. Here’s what I came up with:

[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
    var guyWire = new GeneralGuyWire();
    guyWire.Wire();
}

/// <summary>
/// Tests that the IoC container can resolve instances of each Controller.
///
/// Assuming that constructor DI is used throughout the system, this will
///  indirectly test that all dependencies have been correctly registered.
/// </summary>
[TestMethod]
public void Wire_CanResolveAllControllers()
{
    Assembly
        .GetAssembly(typeof(HomeController))
        .GetExportedTypes()
        .Where(t => MvcContrib.ControllerExtensions.IsController(t))
        .ForEach(c => Assert.IsNotNull(ServiceLocator.Current.GetInstance(c)));
}

A few things to note:

  1. I’m configuring my container using the GuyWire pattern described by Fabio Maulo.
  2. I’m using ControllerExtensions from the MvcContrib project to identify controllers.
  3. I’m accessing the IoC container via the Common Service Locator.
  4. This only tests the dependencies that are referenced by dependency injection, and won’t pick up on any missing registrations that are only referenced via service locator (you’d have to write separate itty-bitty tests to check those registrations).

What do you think? How, if at all, do you test your IoC container registrations?

Page 3 of 86«12345»102030...Last »