Friday, March 14, 2008 -
Many people have asked over the last few years if it was possible to use SubSonic without Active Record. They didn't like the idea that every object could interact with the database and wanted a more "locked-down" approach. I offered some interim templates to get around this, but with version 2.1 we've advanced this idea further and included the ability to override the object base class entirely.
Services, Managers, Helpers, Repositories
There just really isn't a good word for this class but I think people have come to embrace the word "Repository" to refer to your database/data store. Hopefully we can agree on the concept here rather than the wording - if not let me know and I'll do my best to duck responsibility... If you like ActiveRecord - no worries, it's still our default. If you are curious and want to know more about this Repository thing and how it works - you can watch this screencast (download WMV here). A final note to say that we're still in beta - so your thoughts count!
What is your opinion on the public-facing DB class? As one of my own conventions, I just mark the DB class as internal and write my own DB-proxy "Logic" classes. What's your opinion?
Zack
When working with an aggregate (Order, LineItem, ShippingAddress, etc) and aggregate root (Order), it's often very useful to allow the Repository to fetch the entire object graph. This cleans up code such as the following:
Order order = DB.Get(123);
double total = order.CalculateTotal();
where CalculateTotal is implemented as follows:
public double CalculateTotal()
{
long total = 0;
foreach (LineItem item in _lineItems) total = (item.Quantity * item.UnitPrice);
}
You'll find that without the Aggregate / Aggregate Root feature in the data access code, it's very hard to write the above code while staying Persistant Ignorant.
And yes, you could just store the Order Total as part of the order, but the same scenario applies to the ShoppingCart Aggregate (Cart, CartItem) where you may want to recalculate the cart's total on the fly every time (ie.."A change in product price should be reflected in all carts not in the Checkout process...") or ("From 5pm-6pm CST is happy hour, all products are 10% off during that time")..
Just a thought..
I like the way you've changed the base record class and removed the extra methods. This would make it easy (at compile time) to migrate existing code, should we decide to go down this lane.
I'd like to see a UML diagram of your class hierarchy (for generated objects), because it changed since 2.0.
Thanks,
Jason
Secondly: SEE ROB, *others* think the same bat-$h1t-crazy stuff that I do! MUA HA HA HA HA
Ok but seriously, before Dotnetshadow, I think what you might want to do is
1. Compile your SubSonic layer (Domain/Repository) into its own assembly
2. Have that assembly be referenced within another project, we'll call it "Service"
3. Have your BL assembly reference the "Service" assembly
4. Have your UI reference the BL
The problem is that if you're just logically seperating your code within your project, its just that: a logical seperation. The only thing preventing the UI from getting to the DAL is the developer.
Splitting it up into seperate assemblies helps a bit in that only projects referencing the Domain/Repository assembly will be able to call the code...but this doesn't stop said developer from referencing those pieces directly in the UI project. Still better then nothing.
What Rob pointed out to me when I had a similar question was that in the scope of an ASP.NET web application you have to consider the applications context. Any code utilized within a project is governed by the project, even other assemblies. My issue was that I wanted my DAL assembly to own its own config file and not have to put it in as part of the overall project's config...but you just can't do that (or you can, but your web.config still needs to know where to look for the custom config file). So there's no way to totally seprate your DAL from your application unless you create it as a totally seperate boundary (webservice/remoting)...which is valid but may be overkill depending on your application.
Anyway, hth.
D
When do you guys anticipate the final release of 2.1 that includes this new Repository Base Class?
MSD