C# Unit-of-Work Design Pattern for Multiple Storage Types

cdatabasedesign-patternsunit-of-workwindows-registry

I'm trying to implement the unit-of-work pattern for mutliple storage types like the windows registry, a database or the app.config but I cannot figure out how to do it. All examples I find use Entity Framework which already is a UoW so it doesn't help much. What I'd like to store is a simple Setting object.

From http://martinfowler.com/eaaCatalog/unitOfWork.html I understand that

A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.

So I probably should start with a class that has two settable properties and one that tells me whether it's dirty and needs an update.

class Setting
{
    private string _value;

    public Setting(string name, string value)
    {
        Name = name;
        _value = value;
    }

    public string Name { get; set; }

    public string Value
    {
        get { return _value; }
        set
        {
            _value = value;
            IsDirty = true;
        }
    }

    public bool IsDirty { get; private set; }
}

then I guess I need a base repository:

abstract class SettingRepository
{
    private readonly List<Setting> _settings = new List<Setting>();

    public abstract IEnumerable<Setting> Get(Setting setting);

    public void Add(IEnumerable<Setting> settings)
    {
        _settings.AddRange(settings);
    }

    public abstract int SaveChanges();
}

and a unit-of-work as SettingContext:

abstract class SettingContext
{
    protected SettingContext(SettingRepository settings)
    {
        Settings = settings;
    }

    public SettingRepository Settings { get; }
}

Now I'm not sure where I should put all the Update/Insert/SaveChanges logic? A database would for example support transaction whereas the windows registry not.

Do I need different repositories for each storage type or do I need different unit-of-work aka contexts for each of them? I'm really confused.


I don't know what exactly I should do next. Maybe I think to much Entity Framework and try to implement it in a too similar way like this:

using(var context = new SettingContext(new RegistryRepository()))
{
    context.Settings.Add(new Setting("Foo", "Bar")); // this should be created
    context.Settings.Add(otherSetting); // this should be updated
    context.SaveChanges();
}

Best Answer

Your approach is fine so far. The "Unit-of-Work" class should get the responsibility to keep track of the changes to your "settings entity" for one "transaction" (it could do this, for example, by keeping a list of commands or changed objects, if there would be more than one object involved), and the abstract repository should provide an abstraction for the CRUD operations (so there will be one concrete repository implementation for each type of storage, that is fine). The "Commit" operation of the "UoW" then just loops over the commands or changed objects and uses the CRUD operations of the injected repo to store the data/changes.

However, if all the data you have to manage is contained in just one settings object, and the update operation is just to write that object into the storage in one transaction, using a "Unit-of-Work" approach is probably overkill. UoW makes more sense if you need some kind of parentheses around a complex transaction, involving multiple objects. For your Settings object, a repo with methods like SaveSettings and LoadSettings is probably sufficient.