In the 1990s I coded on a few systems where the architecture was that we attached database functionality to our business objects, so you could do something like
someObject.Value = 4;
someObject.Save();
While this looks appealing, this pattern (I later learned that it is called active record) has fallen out of favour, in favour of a model where the database code is contained not in each object, but in a layer that deals with database and nothing else, e.g:
someObject.Value = 4;
dataLayer.Save(someObject);
Now the data layer depends upon the object model, and not vice versa. Database code is grouped together, and is easier to change or replace. These days it's often services as well as databases that data comes from and goes to.
We have the "layered" application as the default mainstream pattern. However there have been new ideas percolating. Inversion of control gives us tools to manage and rearange these layers.
I read Jeffrey Palermo's Onion Architecture and found myself nodding in agreement. I don't really mind how much it resembles Hexagonal, it's good either way.
This is a workable, flexible model, where the object model is made from Plain Old Objects with no special attributes, interfaces or base classes, and knows nothing about any persistence, service or UI layers.
I have also been watching Rob Conery's ASP.net MVC storefront demo video series. It's excellent. Despite supposedly being about the asp.net MVC kit, it shows a lot of good things about a LINQ to SQL data layer, IOC, mocking and testability. And the pattern is much like the onion. (These videos may no longer be on the asp.net MVC site. You can find them at http://blog.wekeroad.com/mvc-storefront/ )
But the problem with LINQ to SQL in the default configuration is that the object model is not central, it is in the LINQ data layer.
There are two ways around this,
First, make LINQ to SQL worth differently, to instead make LINQ to SQL use the object model rather than its own objects. Ian Cooper shows how to do this in his series.
Secondly, you can use the objects generated by LINQ to SQL as data transfer objects only, and copies data from them into the object model. Rob Connery takes this approach and it is surprisingly painless.
In part 10, Rob Connery does something surprising to me - he makes the Shopping cart object aware of the repository interface, so that it can save dependant data. It is given a repository interface on creation, in a Dependency Injection pattern.
This is interesting, this object is using the active record pattern? And if so, is it a bad thing? The coupling that made this a bad idea originally is not present.
To my mind this arangment is not ideal. It may be better to push this code out one layer and attach it to the domain object with extension methods. Extension methods in general give an interesting new possibility - that the object itself is just a data container, but with the right extensions in play it knows how to save itself, or display itself, or whatever the current layer requires.