views:

523

answers:

3

The project I'm working is using n-tier architecture. Our layers are as follows:

  • Data Access
  • Business Logic
  • Business Entities
  • Presentation

The Business Logic calls down into the data access layer, and the Presentation layer calls down into the Business Logic layer, and the Business entities are referenced by all of them.

Our business entities essentially match our data model 1-1. For every table, we have a class. Initially when the framework was designed, there was no consideration for managing master-detail or child-parent relationships. So all of the Business logic, data access, and business entities, only referenced a single table in the database. Once we started developing the application it quickly became apparent that not having these relationships in our object model was severely hurting us.

All of your layers (including the database) are all generated from an in-house metadata-database which we use to drive our home-grown code generator.

The question is what is the best way to load or lazy load the relationships in our entities. For instance Let's say we have a person class that has a master-child relationship to an address table. This shows up in the business entity as a collection property of Addresses on the Person object. If we have a one-to-one relationship then this would show up as a single entity property. What is the best approach for filling and saving the relationship objects? Our Business entities have no knowledge of the Business Logic layer, so it can't be done internally when the property get's called.

I'm sure there is some sort of standard patter out there for doing this. Any suggestions?

Also, one caveat is that the DataAcess layer uses reflection to build our entities. The stored procedures return one result selt based on one table, and using reflection we populate our business object by matching the names of the properties with the names of the columns. So doing joins would be difficult.

A: 

What language are you using? What you described is exactly what the Entity Framework does in .Net. But you didn't share what language you were using and I'm assuming you don't want to rewrite any of your datalayer.

Vyrotek
The entity framework was/is not an option. We are using vb.net I'm interested in the extension methods approach, but this would be difficult consider we are databinding in WPF
Micah
+1  A: 

An approach I've used in the past is to make the container type smart enough to fetch the required objects. eg:

public class Relation<T>
{
  private T _value;

  private void FetchData()
  {
    if( LoadData != null ) {
      LoadDataEventArgs args = new LoadDataEventArgs(typeof(T), /* magic to get correct object */);
      LoadData(this, args);
      _value = (T)args.Value;
    }
  }

  public event EventHandler<LoadDataEventArgs> LoadData;

  public T Value {
    get {
      if( _value == default(T) )
        FetchData();
      return _value; 
    }
    set { /* Do magic here. */ }
  }
}

Then you declare it on your entity like:

[RelationCriteria("ID", EqualsMyProperty="AddressID")]
public Relation<Address> Address {
  get; set;
}

And it's up to the loader of the type that declares the Address property to add a handler to the LoadData event.

A similar class implements IList to give you a one-to-many relationship.

Andrew Kennan
That's an interesting approach, but doesn't that couple my Busines Entities to my DAL or BLL?
Micah
+2  A: 

I highly recommend looking at Fowler's Patterns of Enterprise Architecture book. There are a few different approaches to solving this sort of problem that he outlines nicely, including entity relationships.

One of the more compelling items would be the Unit Of Work pattern, which is basically a collector, that observes the actions performed on your entities, and once your done with your action, it batches the appropriate database calls, and makes the request to the database. This pattern is one of the central concepts used by NHibernate, which uses an object which implements IDisposable to signal the end of the "work". This allows you to wrap your actions in a using, and have the unit of work deal with the actions for you.

Edit: Additional Information

This is a link to the basic class structure of the Unit of Work...not really the most exciting thing in the world. Fowler provides more details in his book, some of which you can see here. You can also look at the Session object from NHibernate as a possible implementation ( I was able to track down the ISession interface...not sure where the implementation lives)

Hope this helps.

ckramer
ckramer - Can you pull the information from somewhere and post it here as to what that pattern looks like? I'll mark you as answered then.
Micah