R – How should the Data Access Layer be structured

Architecturedata-access-layer

I initially designed my system following the s# architecture example outlined in this codeproject article (Unfortunately, I am not using NHibernate). The basic idea is that for each domain object that would need to communicate with the persistence layer you would have a corresponding Data Access Object in a different library. Each Data Access Object implements an interface and when a domain object needs access to a data access method it always codes against an interface and never against the DAOs themselves.

At the time, and still, I thought this design very flexible. However, as the amount of objects in my domain model has grown I am finding myself questioning if there isn't an organizational problem here. For example, almost every object in the domain ends up with a corresponding Data Access Object and Data Access Object interface. Not only that, but each one of these is in a different place which is more difficult to maintain if I want to do something simple like shift around some namespaces.

Interestingly enough, many of these DAOs (and their corresponding interfaces) are very simple creatures – the most common has only a single GetById() method. I end up with a whole bunch of objects such as

public interface ICustomerDao {
  Customer GetById(int id);
}

public interface IProductDao {
  Product GetById(int id);
}
public interface IAutomaticWeaselDao {
  AutomaticWeasel GetById(int id);
}

Where their implementors are usually very trivial too. This has me wondering if it wouldn't be simpler to go in a different direction, maybe switching my strategy by having a single object for simple data access tasks, and reserving the creation of dedicated Data Access Objects for those that need something a little more complicated.

public interface SimpleObjectRepository {
      Customer GetCustomerById(int id);
      Product GetProductById(int id);
      AutomaticWeasel GetAutomaticWeaselById(int id);
      Transaction GetTransactioinById(int id);
}
public interface TransactionDao {
  Transaction[] GetAllCurrentlyOngoingTransactionsInitiatedByASweatyGuyNamedCarl();
}

Does anyone has any experience with an architecture like this? Overall I am very happy with the set-up as it is now my only concern being management of all these little files. I am still wondering however what other approaches toward structuring the Data Access Layer exist.

Best Answer

I recommend against the simple approach other than in simple systems, usually I think your better creating a custom repository for each aggregate and encapsulating as much suitable logic as you can within it.

So my approach would to have a repository for each aggregate that needs it, such as CustomerRepository. This would have an Add (save) method and, if suitable for that aggregate, a Remove (delete) method. It would also have any other custom methods that apply including queries (GetActive) and maybe some of those queries could accept specifications.

This sounds like a lot of effort but other than the custom queries most of the code is, at least if you are using a modern ORM, very simple to implement so I use inheritance (ReadWriteRepositoryBase where T: IAggregateRoot) and/or composition (calling out to a RepositoryHelper class). The base class might have methods that apply in all cases, such as GetById.

Hope this helps.

Related Topic