Entity Framework 4.1 Hooks – DRYing it up with EFHooks
21 June 2011
One of the things I fell in love with about Rails is its automatic management of timestamps on data. When you create a new entity, it sets the created_at field. When you Update it, it sets the modified_at timestamp.
For a long time I’ve used NHibernate as my ORM of choice for .NET and registered listeners for the pre-insert and pre-update events in NHibernate to handle this for me. Now that Entity Framework 4.1 is out and becoming more useful I was interested in seeing how similar things could be done.
Entity Framework’s extension points are very limited compared to what NHibernate is capable of, but there is enough there to get you through most borderline scenarios you’ll hit while working with Entity Framework.
The problem I have with using the extension points is that you have to embed code inside your DbContext class to hook into the inserts, updates and deletes. This means you’re mixing concerns of hooking into the extension point and the logic of what the hook must actually do. This means it becomes difficult to test your hooks in isolation and that your DbContext class can become exceptionally long.
In comes EFHooks. It’s a project I’ve just started to make it easier to hook into Entity Framework. Check the code out on GitHub here.
EFHooks allows you to separate the concerns of writing pre-action hook code from accessing the extension points and registering your hooked code for execution. This means unit testing your hook without using a DbContext becomes easy.
Here’s an example of a hook to run before any entity that inherits from ITimeStamped gets inserted. Everything is strongly typed, so only ITimeStamped entities will be passed into this hook.
// TimestampPreInsertHook.cs
public class TimestampPreInsertHook : PreInsertHook<ITimeStamped>
{
public override void Hook(ITimeStamped entity, HookEntityMetadata metadata)
{
entity.CreatedAt = DateTime.Now;
}
}
This means you don’t need to write code to set your CreatedAt date every time you create an entity that implements ITimeStamped. By the same pattern you could use .NET reflection on System.Object and not even have to use an interface.
Note I said “pre-action” – This handles 99% of the use cases I’ve ever hit. I’m working on a way to handle post-action hooks as well and I’ll have it all in a Nuget package as soon as it’s stable.
Check the code out, build it, play with it and please let me know if you have any problems with it.
(Update: Post-actions are also implemented and the package is available on NuGet here)
Links: