Brain Twist: .NET MVC 3, Entity Framework 4.1, and TDD
Talk about taking a large bite.
In the interests of pushing my .NET knowledge, I began migrating the Geist character sheet project that I’d started in Django to .NET MVC 3. I hadn’t done MVC in .NET since MVC 1 was beta’d, but hey, MVC is MVC is MVC. Right?
So in the interests of making things more interesting and more testable, I decided to dive into the Entity Framework 4. My beginning read of POJOs in Action, along with my previous experience with .netTears–I mean, .netTiers–had me generally familiar with the concepts of entities, contexts, and repositories.
Kicker is, POJOs is just a book (and one I’ve barely dived into), and .netTears uses code generation, meaning I could get away with treating it as just a very hefty ORM in the applications it was in. Generate and go.
Getting my fingers in it was a whole ‘nother experience.
Somewhere in the last year of development, without consciously noticing, I became rather attached to test-driven design, meaning getting a testing framework in place was priority one. I opted for xUnit.net 1.8 for this project, despite it being unconventional in terminology and background. Easily enough integrated with Visual Web Developer 2010 Express, although I wish like hell that the GUI runner would automatically re-execute when the solution is compiled. Where’s autonose when I need it?
Time for entities!
I went for code-first, meaning that I write Plain Ol’ CLR Objects as entities (not quite the same ring as Plain Ol’ Java Objects, but these are things like “CharacterSheet”, “Trait”, “XPLog”), a repository (or several) to manage them (handles CRUD-ish methods), and one or more contexts (handles the persistence). One reason for my interest in the EF style of doing things is that is allows the easy swap out of contexts.
For instance, in the main project, as it would normally run, my “context” is a SQL Server database. Ho-hum, whatever. Same stuff we do everyday.
But lots of people bitch about how you shouldn’t be unit testing against a database. Not only is it slow, it leaves you dependent on services that might not be available (like a remote test DB).
So in the test project, my context becomes an in-memory database (or, shall we say, a set of Lists). It’s all wrapped up in interfaces and abstract classes and such, but it’s a cute gimmick.
It also means that when I get smart and change this character sheet manager to save into a document DB, I’ll have a clean slice of code to swap out. …Theoretically.
This all seems amazingly simple when I type it all out. Getting it working properly was a sunovabitch.
Outdated, confusing guides
Some focus on EF 4.0. Surely there can’t be too big a difference between 4.0 and 4.1, right? Um, there are a few important ones. Some focus on 4.0 and build on old guides that are incomplete in their explanation, and then include changes to the original code that they don’t explicitly mention in the walkthrough. The IObjectSets instead of IDbSets thing threw me off a bit.
Some are for MVC 2 and use some weird data annotations that didn’t appear in the MVC 3 guides.
Some are great, but give an inconsistent compiler warning on the override of the Set() method from DbContext I’m unsure of the best resolution to, since I can’t change the original method. In fact, this is the guide I recommend above the others, but the others provide good (dare I say) context.
I’ll be honest and admit that it took me about 1.5 tries to get a system in place that works.
Compiling, testing, and building
When I shut down for the day yesterday, I had a compiling (albeit with that damned warning) solution, a few unit tests that execute and pass, and a much better understanding of all this mess.
One thing that’s been impressed upon me in kicking all this up is how… open .NET is. Django, the various PHP frameworks I’ve worked in, Rails (way back when), all of them have strong conventions. “This is how validation is done”, “this is how testing is done”, etc. I feel like .NET has more choices, which surprises me in coming back to it.
Next up is validation.