Hanalei, Hawaii 9/2/2010
438 Posts and Counting

It’s Time for This: ActiveRecordEngine for ASP.NET MVC

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:

  1. An “IActiveRecordEngine” API for MVC that would allow you to “plug in” your AR implementation in the same way you might swap out the ControllerFactory or ViewEngine. In the Global.asax you would just “SetActiveRecordEngine(new SubSonicActiveRecordEngine())” and off you go.
  2. Define an IActiveRecord interface for your objects to implement (stuff like Add, Update, Delete, etc)
  3. Create an opinionated Controller<T> that would use this so you don’t have to think about persistence ANYMORE. The idea would be you would use a RESTful approach (like Rails does) with your objects and have a Controller<Post> for example. This controller would already have the “magic 7” actions defined (or magic 5 – depending on how literal you want to be) for CRUD operations and you can add/override as you like.

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!

Related


Gravatar
Eddie Cianci - Saturday, November 14, 2009 - An intriguing idea! I would definitely look at the upcoming "ActiveModel" in Rails 3.0 for inspiration - it's an API that allows some level of ORM agnosticism in ActionPack (the Controllers/Views).

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
Gravatar
Javier Lozano - Saturday, November 14, 2009 - We should talk! This would be cool to implement as a Blade for MVC Turbine! http://mvcturbine.codeplex.com
Gravatar
KevDog - Saturday, November 14, 2009 - I, for one, welcome our new ActiveRecord overlords and would prefer not to think about persistence.
Gravatar
Bayard Randel - Saturday, November 14, 2009 - This sounds very sensible. One of the biggest problems with the Microsoft stack for web development to my mind is that it is not strongly opinionated. This is very liberating of course, and allows you the freedom to create any architecture imaginable, but it also leaves developers with a lot of rope to hang themselves. If Microsoft wants ASP.Net MVC to be as rapidly productive as a framework like Rails, issues like data persistence and object mapping just need to be as simple as possible.
Gravatar
Thomas Wagner - Saturday, November 14, 2009 - I always thought having some of that SubSonic goodness in MVC would be very very cool. Too bad that didn't work out. Personally I think there is much to be said in having ASP.NET mimic some of the better parts of RoR. I strongly believe that your idea would provide some competition in that space and thats good. I think you have quite a following w SubSonic. All the more reason to give it a shot
Gravatar
Vijay Santhanam - Saturday, November 14, 2009 - Great idea! I 100% agree. You should work on this at MS as an engineer/designer/architect. I always thought you were great at designing APIs like you've shown in SubSonic.
Gravatar
Emad Ibrahim - Saturday, November 14, 2009 - ABSOLUTELY man... I hate thinking about persistance. I just want sh*t to work. Opinionated stuff is ok but give me a way to override it - I have opinions too.
Gravatar
phenryll - Saturday, November 14, 2009 - To be honest, this sounds too cool to be true :)

It would be great if you could describe/expose your prototype. I just can't wait ;)
Gravatar
simon - Saturday, November 14, 2009 - The future of MVC is going to be a lot about plugging in components. In the same way that classic ASP.net (I'm coining that term and loving the connotations) is about reuse through user controls. What I would like to see is a persistence engine to which I can pass anything. Even more I would like to see one which can be dropped in as a component. I wrote a bunch more on this at http://stimms.blogspot.com/2009/11/persisting-in-mvc.html
Gravatar
Andrei Rinea - Sunday, November 15, 2009 - Go for it Rob!

If I / we could help let us know.
Gravatar
Laurent Kempé - Sunday, November 15, 2009 - Hi Rob

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
Gravatar
scitesy - Sunday, November 15, 2009 - Great ideas! I especially like the pluggable model. Making persistence an afterthought on .net is long overdue. I'm wondering how the nosql databases such as CouchDB, MongoDB, etc. might be supported through these interfaces. Also, will applications running on Mono be supported?
Gravatar
Hector Minaya - Sunday, November 15, 2009 - great Idea, this is something that asp.net mvc is lacking.
Gravatar
Jeremy D. Miller - Sunday, November 15, 2009 - Whatever you do Rob, go "Composition over Inheritance." The base class for "CrudController" is seductive, but fraught with danger. The inheritance model breaks down after anything beyond simplistic CRUD and new hook methods proliferate. If you do it, my strong advice is to look at Udi Dahan's model of role-based interfaces that can be assembled together rather than an inheritance model.
Gravatar
Simon - Sunday, November 15, 2009 - Speaking of Udi, this just cries out for using domain events. Make it nice and simple to react to things changing.
Gravatar
Liam McLennan - Sunday, November 15, 2009 - Lack of testability is what has always put me off active record. It would be great if your API included support for testing.
Gravatar
Pure Krome - Sunday, November 15, 2009 - Awesomesauce! Bring it Rob! Bring it!

(and heed Jeremy Miller's (as always) words of wisdom).

This is why i lub ASP.NET MVC :)
Gravatar
Iain - Sunday, November 15, 2009 - Great idea, exactly the sort of thing I think MVC needs :-)
Gravatar
Marcel - Monday, November 16, 2009 - This is a great idea and I want it YESTERDAY! One concern though, where would the business rules live? At the moment I abstract away my repositories into a service layer and handle most business logic there. This keeps my actions very lean.

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
}
Gravatar
D. Lambert - Monday, November 16, 2009 - +1 Marcel - I'd like to know more about where the business rules are implemented.

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.
Gravatar
Paul W - Monday, November 16, 2009 - Love it!! I've been trying to implement some sort of ActiveRecord pattern on top of LinqToSQL for a while but haven't really got it right. I'd love to see some guidance in this area.
Gravatar
paul - Monday, November 16, 2009 - I like the idea of an opinionated controller; I've been kicking around a similar idea for a while. While I've been using S#harp a great deal lately, one thing I don't like about it is that its templates aren't very smart about inheriting common functionality.

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.
Gravatar
zihotki - Tuesday, November 17, 2009 - I think that this idea is really cool and useful. It will save a lot of time for developers.
Gravatar
Cohen - Tuesday, November 17, 2009 - I really like the idea, especially in combination with the REST urls.

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?
Gravatar
ILog - Wednesday, November 18, 2009 - Some random thoughts:
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?
Gravatar
Manuel Castro - Thursday, November 19, 2009 - I think it's a great idea because it fits very well in a qute common type of ASP.NET application, that type of application where the persistance issue is almost irrelevant.

Keeping an eye on this ..
Gravatar
Josh - Thursday, November 19, 2009 - Rob,

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.