Skip to content

How to support custom types

Mogens Heller Grabe edited this page Oct 11, 2021 · 4 revisions

Let's pretend that you have coded a proper Date value type, which you are using in a model like this (warning: this particular examples does not work yet 😈 ):

class CurrencyPairRate
{
    public CurrencyPairRate(Date date, string @base, string quote, decimal rate)
    {
        Date = date;
        Base = @base;
        Quote = quote;
        Rate = rate;
    }

    [DebaserKey]
    public Date Date { get; }

    [DebaserKey]
    public string Base { get; }

    [DebaserKey]
    public string Quote { get; }

    public decimal Rate { get; }
}

where the Date type looks like this (equality implementation and comparison operators omitted for brevity):

class Date
{
    public Date(int year, int month, int day)
    {
        Year = year;
        Month = month;
        Day = day;
    }

    public int Year { get; }
    public int Month { get; }
    public int Day { get; }
}

Obviously, the Date type is not a common BCL type and it does not have a clear match among the data types available in SQL Server. Therefore, we write a custom mapper that is capable of roundtripping values of this type, also providing information about which type of column to create in SQL Server - the mapper looks like this:

class DateMapper : IDebaserMapper
{
    public SqlDbType SqlDbType => SqlDbType.DateTime;
    public int? SizeOrNull => null;
    public int? AdditionalSizeOrNull => null;

    public object ToDatabase(object arg)
    {
        var date = (Date)arg;
        return new DateTime(date.Year, date.Month, date.Day);
    }

    public object FromDatabase(object arg)
    {
        var dateTime = (DateTime)arg;
        return new Date(dateTime.Year, dateTime.Month, dateTime.Day);
    }
}

and is utilized by adding [DebaserMapper(typeof(DateMapper))] to the property, like so:

class CurrencyPairRate
{
    public CurrencyPairRate(Date date, string @base, string quote, decimal rate)
    {
        Date = date;
        Base = @base;
        Quote = quote;
        Rate = rate;
    }

    [DebaserKey]
    [DebaserMapper(typeof(DateMapper))]
    public Date Date { get; }

    [DebaserKey]
    public string Base { get; }

    [DebaserKey]
    public string Quote { get; }

    public decimal Rate { get; }
}

When this is done, we can safely roundtrip Date value which will be mapped back 🤜 and forth 🤛 to SqlDbType.DateTime as needed. 🎀

Clone this wiki locally