Saturday, November 14, 2009 -
I had dreams of this when I joined Microsoft a few years back – that SubSonic would be the database juice in the ASP.NET MVC story. Or if not the juice then the ActiveCherryOnTop.
The pieces didn’t quite fall into place, though I tried many a time. The issues that I faced were pretty simple – everything I tried didn’t quite fit. No one wants to take a dependency on a specific data access library (which is precisely the thing that Rails does most of the time – and it’s quite freeing to not think about it) – so working SubSonic into MVC didn’t quite fire on all cylinders.
It’s understandable – but I have a better idea now and I want to see if others are willing to engage with me on it. “Others” being the troupe of ORM-dudes out there: NHibernate, LLBL, and the for-pay guys…
Background
I’ve been talking to Phil of late (actually I’ve been mercilessly teasing him) about his work with the EF team on an ActiveRecord story for ASP.NET MVC. I understand the technical aspects of it, but the last thing I can get my head around is using EF to pump ActiveRecord magic into MVC. Sort of like having to ask the US Congress where the restrooms are…
Anyway I told Phil I’ve had a demo sitting here that I’ve been trying to spruce up a bit – a “SubSonic Starter” site for MVC if you will. I followed some patterns that I thought we could reuse for any ORM/DataEngine out there – and so I hit him up with the idea that I really like…
Elevator Pitch
Long story short – we geeked out for a few hours the other night and it was really fun. Here’s what we came up with:
In addition to that, the IActiveRecord interface would define some “sugary” methods such as “GetKeyName, GetKeyValue, GetDescriptorName, GetDescriptorValue” that would allow you to spin up UI elements with the HtmlHelpers. Something like “Html.ControlFor<Post>(x=>x.Title)”.
There’s so much we can do with this – all without caring about which persistence mechanism we use (EF, SubSonic, L2S, NHib – whatever) as long as they implemented the API. Yes – some would do the API better than others, and if that’s the case then your data story is solved isn’t it?
Doing It In Public
It’s tempting to “come up with a proto” and push it out there – and believe it or not I have one – but I’d like to see if I can take the lead on this and come up with an API that works for the most common scenarios. I understand that “opinionated” approaches to problems generally don’t work well with a committee – all the same I don’t want to do this in the dark.
Before I do anything (as I’m already stretched pretty thin) – I wanted to see what people thought of this idea. So – lemme have it! Good? Bad? Things you’d like to see?
I’ll tweak my prototype based on what you suggest here, and see what I can do with it next!
Yehuda Katz has written about it at http://www.engineyard.com/blog/2009/my-five-favorite-things-about-rails-3/ (and elsewhere) and the GitHub repository for it can be found at http://github.com/rails/rails/tree/master/activemodel
It would be great if you could describe/expose your prototype. I just can't wait ;)
If I / we could help let us know.
I did this last week for a project I am working on, to be able to validate the architecture we have designed. Now we are able to plug 2 O/RM on our project without changing the upper layers. In fact this is not really true because I had one change on my domain models, adding virtual everywhere because NHibernate needs it and Euss doesn't need it. How do you plan to handle those kind of differences?
Cheers
Laurent
(and heed Jeremy Miller's (as always) words of wisdom).
This is why i lub ASP.NET MVC :)
ie. in Create Action.
Service.ProcessOrder(newOrder); // which does quite a few things and persists a number of items
If this 'IActiveRecord' interface is tied to the controller, I would need to make business decisions in my actions methods.
ie. if(newOrder.HasShippingCost) {
ActiveRecordRepository.Insert(newOrder);
ActiveRecordRepository.Insert(new ShippableOrders{Order=newOrder, Cost=newOrder.CalculateCost()}).... bla bla you get the idea
}
The IActiveRecordEngine idea sounds really interesting, but I'd personally like to see that business rules can be encapsulated in the Model, and done so in a way that ensures that the model can be used in multiple MVC sites.
That said, I'm not really sure what the perceived advantage of doing it as an ActiveRecord-style pattern would be? Couldn't you do the same thing w/ a Repository pattern? I guess I've never been a fan of AR, since it (to me) bleeds concerns too much for my taste. But that said, anything that helps us make MVC the lightweight, rapid framework it can be would be a great option in my book.
But should the interface be an IActiveRecord or should you go one level higher on the abstraction tree and go for an IRepository?
If you would like to offer something that takes away the storage concerns from the developer, doesn't a repository sounds more appropriate?
What do you think Rob?
1. I am scared of the future where web developers have only heard something about SQL, don't know exactly what is stored procedure, and respond "excuse me, what?" to an interview question about query execution plan.
2. I write SQL query or sproc call faster than LINQ sentence with intellisense.
3. I dream that ASP.NET MVC comes and makes a revolution in enterprise web portal development with the hundreds of DB tables and thousands of sprocs.
:)))
Rob, do you think ActiveRecord is really scalable? Does it fit to something other than a small home site prototype?
Keeping an eye on this ..
This is a great idea, but I think many ASP.NET MVC developers (particularly those who are simply accustomed to RAD in webforms) are a bit overwhelmed by the plug-in options of ASP.NET MVC. It seems like architectural decisions are the biggest hurdle, even though 90% of web applications are similar enough that they could use the exact same architecture as a starting point.