views:

311

answers:

1

I have a unique situation where I am building a DDD based system that needs to access both Active Directory and a SQL database as persistence. Initially this wasnt a problem because our design was setup where we had a unit of work that looked like this:

public interface IUnitOfWork
{
   void BeginTransaction()
   void Commit()
}

and our repositories looked like this:

public interface IRepository<T>
{
   T GetByID()
   void Save(T entity)
   void Delete(T entity)
}

In this setup our load and save would handle the mapping between both data stores because we wrote it ourselves. The unit of work would handle transactions and would contain the Linq To SQL data context that the repositories would use for persistence. The active directory part was handled by a domain service implemented in infrastructure and consumed by the repositories in each Save() method. Save() was responsible with interacting with the data context to do all the database operations.

Now we are trying to adapt it to entity framework and take advantage of POCO. Ideally we would not need the Save() method because the domain objects are being tracked by the object context and we would just need to add a Save() method on the unit of work to have the object context save the changes, and a way to register new objects with the context. The new proposed design looks more like this:

public interface IUnitOfWork
{
   void BeginTransaction()
   void Save()
   void Commit()
}

public interface IRepository<T>
{
   T GetByID()
   void Add(T entity)
   void Delete(T entity)
}

This solves the data access problem with entity framework, but does not solve the problem with our active directory integration. Before, it was in the Save() method on the repository, but now it has no home. The unit of work knows nothing other than the entity framework data context. Where should this logic go? I argue this design only works if you only have one data store using entity framework. Any ideas how to best approach this issue? Where should I put this logic?

A: 

IMO I would wrap the calls to both of these repos in a service type of class. Then I would use IoC/DI to inject the repo types into the service class. You would have 2 repos, 1 for the Ent. framework and 1 that supports AD. This way each repo deals with only its underlaying data store and doesn't have to cross over.

What I have done to support multiple units of work types, is to have IUnitOfWork be more of a factory. I create another type called IUnitOfWorkScope which is the actual unit of work and it has only a commit method.

namespace Framework.Persistance.UnitOfWork
{
    public interface IUnitOfWork
    {
        IUnitOfWorkScope Get();

        IUnitOfWorkScope Get(bool shared);
    }

    public interface IUnitOfWorkScope : IDisposable
{
    void Commit();
}
}

This allows me to inject different implementations of the unit of work into a service and be able to use them side by side.

void