What has gone before-I had problems installing blog software with my host, so I decided to write my own. I sort of force myself to do ASP.Net MVC instead of ASP.Net Web Forms, and was pleasantly surprised at how much I liked it. Then I went to create my schema and decided to make my life more difficult for myself by having a multi-blog site.
So how to architect my system on top of the LINQ generated layer. Hmm well I'm using MVC. I could just throw my business logic in the Controller classes. Its the way they're described as should be done, but I dunno. I'm not feeling it. I'd like to be able to have my Business rules completely separate from my UI layer so I can put any kind of interface on top that I want. WCF Web Service, Windows Form, Silverlight, whatever. So if I put my logic into the controller, well I'm kind of rooted in the MVC stuff.
So lets see, can I use designs I've used in the past? Why not, should work. The way I generally design my layers is based on using Typed Datasets (kickin it old school in these LINQ days).
My data layer has
- A typed dataset mapped to a database table.
- A gateway class that contains all the SQL that the business layer needs (GetById, GetBySomeOtherValue, Update, Save). Its based on the SqlDataAdapter class. Essentially this is a wrapper object around whatever repository I choose to utilize.
My Business Layer has
- A Collection class which contains a reference to a typed dataset (it contains the reference to hide all the typed dataset methods, simplifying its interface and making it cleaner, but still implementing IBinding so you can bind the object to a UI just like a dataset).
- An Entity class that represents a single row in the collection.
- A Service class to contain the Business logic, and is responsible for calling out to the data layer for retrieving the data.
So I started trying to use this structure with LINQ and found out a few thing pretty quickly.
- I didn't need the typed dataset class at all, LINQ to SQL generates a object for you. So right away thats been replaced by something new.
- Hmm I don't really need the Collection class, this whole design originated before ASP.Net got generics, using something like List basically does this for me. That and the LINQ generated objects are all singular so I can't really have a "DataSet" sort of container, it makes no sense.
Ok so those two were obvious. Now what about the Entity class. Do I still contain the LINQ generated entity objects in my own Entity class (i.e have my own User class that contains the LINQ generated User class)? Would I really want to do that? My first thought was yes I would, and the prime reason was the User object.
I already knew I wanted the User business object to implement IPrincipal. This way when a user logs in I could just put resulting User object into the current threads CurrentPrincipal propertly and pass it around easily. But in order to do that I had t o modify the User class to implement the IPrincipal interface. I knew I didn't want to alter the LINQ generated User class directly (if I had to regenerate the class for some reason I'd lose all my changes). So containment still made sense.
I started down the path of getting all my LINQ entities contained within business objects, and I quickly found I hated it. It just felt like a LOT of busy work. First I had to create the business object, then I had to pass all the property requests down through to the contained objects. I had to put in a slew of error handling in case the contained LINQ entity was null, blah blah blah.
In short, I thought it sucked.
So now what? Hmm there must be a better way. Wait a second. What about partial classes? How the heck could I forget about them? (Well that's easy to answer, I hadn't used them before). What the heck I'll try it. So I extended the LINQ generated User entity with a partial class where I put my code to su pport IPrincipal. It worked! It was fairly clean, it was easy to do, it was easy to work with the class. So far so good (not sure how OO partial classes are, they feel like a cheat to doing true OO and design patterns, but for now I'll reserve judgement).
Now I had to decide, how would I setup my Manager class, should I scrap my Gateway/Repository and just put the code right into the Service?