In this post I would like to share with you very specific Data Connection Creation Pattern that I’m using in some form from many months. I’d already tested it with Entity Framework, MS Dynamix CRM, LinqToSQL and directly with plain ADO / MS SQL connectivity (and mixes of them). It went through several customizations and variations of course, but the whole idea is always the same.
DISCLAIMER: But before I go further I must first warn you, that I’m not a great fan of generic DI/IoC containers, Service Locator or creating thousands unnecessary interfaces only “in case of testing”. I prefer straight approach of direct dependencies and creation, clear and visible instance ownership, optimized lifetime management and code being primarily effective and easy to debug over working magically according to some god-class. While I consider myself primarily backend (workflow / batch / server processing) developer you should not be surprised that I sometimes micro-optimize my design from the beginning, not only after observing performance problems – it’s on purpose – I need my background tasks to not waste nor CPU neither memory to effectively process thousands Work Items at once.
I also do recommend reading this book: Writing High-Performance .NET Code to better understand why I’m sometimes doing what I’m doing (or not 🙂 )
This particular pattern has been influenced by trying to replace and join together in an effective manner some ideas implemented by such (anti)patterns like Repository, Item of Work, Service Locator and so. My core idea was to precisely:
- control Data Access in heavily multi-thread processing environment,
- keep it to be as lightweight as possible,
- present to the user (in this situation – developer who will be utilizing this pattern) simple, functional and clean interface that he can intuitively work with.
Depending on project I’ve been using this patter, I’d been incorporating more or less interfaces, but at least two of them were always present:
- ISharedContextFactory – responsible to cache data (and sometimes more) needed to connect to Data Source; and most of the time presenting two methods: CreateContext(), CreateReadOnlyContext() – both returning IDisposabled instance of a second interface:
- ISharedContext – this interface gives the only access to instances of all known repositories through read-only accessors (properties). Depending on environment support it might also contain two methods: Commit() and Rollback() that are expected to finish whole item-of-work with desired output.