Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map two DB column to one data type using Dapper

Tags:

c#

dapper

Is it in anyway possible for dapper to map two columns from the database to one .Net data type?
My scenario is that I have monetary values in the database represented as two columns.

Cost         Decimal(19,4)  
CostCurrency char(3)

And I want it mapped to the custom data type Money

public partial struct Money
{
   public Money(decimal amount, string currency)
   {
   }
}

For example on the insurance entity:

public class Insurance
{
    public string Id {get;set;}
    public Money Cost {get;set;}
}

I've been looking at SqlMapper.TypeHandler<Money> but it only seems to be able to read/write one column at a time.

like image 370
Magnus Avatar asked Apr 24 '26 19:04

Magnus


2 Answers

I tend to find that any mapping of complex properties can be greatly simplified by using private properties to represent the data storage. Dapper will map to private properties.

public class Insurance
{
    #region Data
    private decimal Cost{get{return this.CurrentCost.Amount;} set{this.CurrentCost.Amount = value;}}
    private string Currency{get{return this.CurrentCost.Currency;} set{this.CurrentCost.Currency = value;}}
    #endregion


    public string Id {get;set;}

    //Changed prop name to not confuse it with storage columns
    public Money CurrentCost {get;set;}

    public Insurance(){
        //initialize this so that it won't blow up on mapping
        this.CurrentCost = new Money();
    }
}

At first blush this feels like we're marking up our object quite a bit to make it persist and map. But it's so straight-forward with no magic mapping that it just works. You can unit test all of it too. And even a project with hundreds of persisting objects this technique will only take up a sliver of time and be totally flexible and manageable throughout the growth of the project.

like image 109
BlackjacketMack Avatar answered Apr 26 '26 09:04

BlackjacketMack


Turns out I needed to use the Split functionality of dapper:

var insurance = (await con.QueryAsync<Insurance, decimal, string, Insurance>(
                   sql,
                   (entity, cost, costCurrency) =>
                   {
                       entity.Cost = new Money(cost, costCurrency);
                       return entity;
                   },
                   splitOn: "Cost, CostCurrency",
                   param: new { Id = id })).Single();
like image 42
Magnus Avatar answered Apr 26 '26 10:04

Magnus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!