Entity Framework Relationship Mapping – Best of both worlds (EF4.1/CTP5 Code only & fluent API)

Author: Stuart  //  Category: ASP.NET, CTP5, EF4.1, Entity Framework

This is a quick post as I don’t see myself finding the time to finish my series on scalable code using Entity Framework 4.1 (currently CTP5) anytime soon.

Disclaimer: This is not an excuse for poor architecture and your design should have your concerns seperated well as you can get into trouble with partially loaded entities saving back to the db.

One of my favourite things about the code only persistance ignorant approach now available in EF4.1 is the ability to manage my relationships a little ad-hoc.

Why does the word Ad-Hoc sound so hacky and why do I like it?

I like to have a self documenting model. I don’t like the next guy to have to dig around to work out relationships or pour over database design diagrams for hours. I also don’t like persistance awareness that comes with the designer because of the extra database traffic it generates for simple crud operations when dealing with the persistance ignorant web.

So that leaves me with a dilema. Do I map my relationships properly in my model (easy for the next guy), or do I make my objects lame so you don’t have to load aggregate roots all the time for simple options (more scalable).

Now it seems we can do both. For example, I’m going to use one of the conveniently simple scenarios that is so commonly used to sell these things. The simple blog model.

public class Post
{
     public int Id { get; set; }
     public string Title { get; set; }
     public string Content { get; set; }

     public List Comments { get; set; }
}

public class Comment
{
     public int Id { get; set; }
     public string Title { get; set; }
     public string Content { get; set; }

     public Post ParentPost { get; set; }
}

So how do I add a comment to this scenario?

I need to load the post and then save the post with the new comment to ensure the comment has the correct PostId in the databsae (or generated reference table if you let EF do it for you). That stinks. Especially if comments are being created extremely frequently and are coming from a website. The post is not stored anywhere after the page it’s on it is served. Using caching can lead to persistence clashes.

So I need to load the post just to add a comment. Not so bad in the above example, but if Post has varchar(max) fields and is a large complex object in a complex model, this starts to get very ugly and slow.

A lot of developers go for lame objects to resolve this, which is cool and I totally understand why, but this can lead to performance issues on the way out of the database as the generated sql ain’t exaclty optimised. I’ve found EF does it better when the model’s in tact properly. It also makes code harder to read and understand and makes it much easier to corrupt data in many cases.

Now we can have our cake and eat it too. All we need to do is add the foreign key property to the comment object and then tell the fluent api it references the object.

public class Comment
{
     public int Id { get; set; }
     public string Title { get; set; }
     public string Content { get; set; }

     // Add post id
     public int PostId { get; set; }

     public Post Post { get; set; }
}

Fluent mapping

    public class CommentMapping : EntityTypeConfiguration<Comment>
    {
        public CommentMapping()
        {
            HasKey(x => x.Id);
            HasRequired(x => x.Post).WithMany().HasForeignKey(x => x.PostId);
            ToTable("Comment");
        }
    }

This tells EF what I need it to know. Now I can just go ahead and create a comment object anywhere, anytime and save it to the database. Next time I query the post or comments, the relationship will be perfectly in tact.

This is a big deal for me. It means in MVC and jquery scenarios I can easily create small listitem objects on larger more complex objects without loading full heirarchies first. I just set PostId, save it and forget (like with lame objects).

However I can still query the data with

 from c in Post.Comments
 where c.user = "me"
 select c

This is especially useful if your model goes 3 or 4 levels down a heirarchy and you want to selectively populate ViewModels to make it scalable.

There are a few things to look out for, like enforcing foreign keys on your DB and designing your app to make it clear the new object can’t query back to the post, but his solves a long running problem I’ve had with linq to sql, EF1 and EF4 when working on the web.

StructureMap Thread Safety – Dangers of pattern chasing

Author: Stuart  //  Category: ASP.NET, MVC

Anyone who has been developing for a while will relate very much to the experience of coming up against a young developer full of ideas and the latest design patterns without understanding the background. I have half written a seperate post about the principals of design patterns which I will link to here later.

This brings me to the more immediate problem. I recently encountered a site written by a very clever developer who had probably just finished reading Scott Millet’s wonderful ASP.NET design patterns book and had rushed off to download a copy of StructureMap for his dependancy injection. Now I wasn’t there at the time, but I believe the argument was “It’s a  standard design pattern and enables unit testing..etc etc” – First mistake.

First off, the timeline never allowed for unit testing. Secondly it was as simple web form with no real business logic which makes the bet unit test to open your freakin browser and try it, and thirdly it was a highly visible, high traffic site.  NEVER try something you don’t understand in that sort of scenario, especially a community project in its infancy.

Down to the code..

The offending piece of code was in a bootstrapper that takes care of your dependancy injection concerns by instantiating classes on an application level. It means that you can refer to concrete classes anywhere in your controllers, thereby removing the perenial problem developers have with MVC.. no real underlying context.

Bootstrapper.ConfigureStructureMap();

Now in the bootstrapperregistry he had:

..
ForRequestedType<IUserRegistrationService>().TheDefaultIsConcreteType<UserRegistrationService>();
..

At first glance, nothing would appear to be wrong with this. He had service classes with instance methods that required dependancy injection and bootrapped them to the application with StructureMap. The problem is that those services then became single instances for the whole app and thereby were not thread safe. This could have easily gone unnoticed if we hadn’t tested this with multiple users on the same site at the same time. You guessed it details were being shared between users – worst nightmare for an application.

Safe ways to use bootstrapping

Personally, I don’t think there really is one. You’re hiding a lot about your classes and attaching them to a part of the http request process that’s not per request. Tempting to do this when you’re a software developer more than a web developer, but best avoided.

If you MUST bind everything somewhere so you can use it without an extra line of code, a Base controller or page would be a safer place (although it can have same problems in MVC).

My personal preference is to use Factory classes to spit out fresh little instances of your classes. For example, here’s the sort of thing I’m using in a multi database site with EF4. Would work for services too:

..
public class MyDataContextFactory
{
    public static MyDataContext1 GetMyDataContext1()
    {
        MyDataContext1 context = new MyDataContext1 (ConfigurationManager.ConnectionStrings["MyDataContext1"].ConnectionString);
        context.Database.Initialize(true);
        return context;
     }
... etc

Moral of the story

The obvious solution is to correct the usage of StructureMap, but because the developer was “pattern chasing” he came up with all sorts of explanaitions like MVC1 had thread safety issues with session (I doubt it would’ve made it to market if it did – bad implementations of view caching aside).

So the best way to improve your patterns is to start with a smaller project, build it the way you know (albeit spaghetti code) and refactor to a pattern that you understand one part at a time. Otherwise you can well go barking up the wrong tree and worst of all release massive problems into the wild on your site..

I’m also not a fan of StructureMap for this reason… and this is another reason to be careful about community projects. A commonly forgotten fact in web development is just becuase you know how to do something right, doesn’t mean the rest of your team will. Some things are just plain dangerous to leave in your code and I find it helps to try and predict the stack with a hangover.. if you get it way wrong, then you don’t know enough about your own code.