Using Enumerations with NPoco

Recently, we tried to use the Enumerations project with NPoco. In our case, we wanted to get the enumeration Value to persist as an Int in our database. At first it seemed like we may need to create a Fluent Mapping for each property. But then I discovered a better breakdown of custom mappers and it turned out to be a lot easier than expected.

When you take a look under the hood, NPoco encapsulates the configuration bits of the Database class into an IDatabaseConfig. The important member to note is the IMapper property.

public interface IDatabaseConfig
{
    IMapper Mapper { get; set; }
    PocoDataFactory PocoDataFactory { get; set; }
    DatabaseType DatabaseType { get; }
    string ConnectionString { get; }
}

IMapper

NPoco uses this interface to abstract the process of mapping to and from your pocos. Out of the box, it ships with a basic mapper aptly named DefaultMapper. Obviously, the point here is to allow us to change out the mapper so, how do we do that?

It Starts With the DatabaseFactory

If you’re not using one yet, a DatabaseFactory in your NPoco application is a must. Not only does it support our cause here, but it will make your life a lot easier down the road for all sorts of other stuff.

Once we have one, here’s how we swap out the mapper.

public static class MyFactory
{
    private static NPoco.DatabaseFactory InitializeFactory()
    {
        return NPoco.DatabaseFactory.Config(x =>
                {
                    x.WithMapper(new EnumerationMapper());
                });
    }
}

We then need to make sure we use our factory anywhere we inject or request an IDatabase.

using(var db = MyFactory.InitializeFactory().GetDatabase())
{
    ...
}

The Custom Mapper

One way we could implement our custom mapper would be to just implement IMapper. But we’re not trying to reinvent the wheel here. Lucky for us, the methods on DefaultMapper were implemented as virtual.

public class EnumerationMapper : DefaultMapper
{
    public override System.Func<object, object> GetToDbConverter(System.Type destType, System.Type SourceType)
    {
        if (SourceType.IsEnumeration())
            return x => SourceType.GetProperty("Value").GetValue(x, new object[] { });
        return base.GetToDbConverter(destType, SourceType);
    }

    public override System.Func<object, object> GetFromDbConverter(System.Type destType, System.Type sourceType)
    {
        if(destType.IsEnumeration())
            return x => destType.BaseType.GetMethod("FromValue").Invoke(null, new[] { x });
        return base.GetFromDbConverter(destType, sourceType);
    }
}

How the Mapper Is Used

When NPoco is mapping to a database value: GetToDbConverter is called.
When NPoco is mapping from a database value: GetFromDbConverter is called.

In this implementation we simply use the Value property and the FromValue method to convert our integer value from the database into an Enumeration instance.

Source Code

If you would like a more in-depth look, I’ve provided the source code for the samples here on github: https://github.com/davidsavagejr/NPocoEnumerations