PetaPoco - Custom mapping with the Mapper interface

Monday, 4 April 2011

A couple of users have asked for better strict POCO support in PetaPoco. Specifically the ability to remap column and table names without decorating POCOs with attributes.

This post is about PetaPoco - "a tiny ORMish thing for your POCOs". Read more on the PetaPoco Project Page.

The easiest way to use PetaPoco is to decorate your POCOs with attributes that declare which properties should be mapped to which columns. Sometimes though, this isn't practical or some believe its too intrusive. So I've added a way to declare these bindings separately.

The PetaPoco.Database class now supports a static property called Mapper which acts a hook through which you can install your own column and table info mappings.

First, you need to provide an implementation of PetaPoco.IMapper interface:

public interface IMapper
{
    void GetTableInfo(Type t, ref string tableName, ref string primaryKey);
    bool MapPropertyToColumn(PropertyInfo pi, ref string columnName, ref bool resultColumn);
}

When the GetTableInfo method is called, the tableName and primaryKey will be set to the default values that PetaPoco has determined. Just change them if you want something else - remember to check the type first.

Similarly for the MapPropertyToColumn method - just change the values of the columnName and resultColumn to suit your needs. Return true to allow the mapping, or false to ignore it.

Once you've implemented the IMapper, you just need to tell PetaPoco about it which is done through the static Mapper property:

PetaPoco.Database.Mapper = new MyMapper();

Note there are a few limitations with all of this but I think the trade off for simplicity is worth it.

  1. The mapper is shared by all Database instances. PetaPoco caches these column mappings globally so it's not possible to provide different mappings for different database instances.
  2. You can only install one mapper.

Available in github now, NuGet as soon as it back up.

« PetaPoco - Transaction Bug and Named Parameter Improvements PetaPoco - Smart Consecutive Clause Handling in SQL Builder »

1 Comment

Really like PetaPoco so far, so refreshing. I have a question; do you have any plans to support nested POCOs where a POCO contains another POCO as a property? The convention could be that the name of the nested POCO property matches the name of a joined table in the query, or some kind of alias prefix in the query. This would really help when hydrating domain models where nested POCOS are used for structuring and object reuse. Otherwise my domain models would either have to be very flat or I'd have to write code to hydrate the domain entity from the POCO, both of which I'm reluctant to do

This is the kind of code I would love to see work with PetaPoco, the vat property would be automatically populated :

using System; using System.Collections.Generic; using System.Linq; using System.Text; using PetaPoco;

namespace PetaPocoTest { public class VAT { public string id {get; set;} public string description {get; set;} public double rate {get; set;} }

public class Fund
{
    public long id {get; set;}
    public string description {get; set;}
    public string GLCode {get; set;}
    public VAT vat {get; set;}

    public Fund()
    {
        vat = new VAT();
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var db = new PetaPoco.Database( "GeneralLedgerDatabase");

        // Show all articles    
        foreach( var fund in db.Query<Fund>("SELECT * FROM fund left outer join VAT on VAT.ID = fund.vatid"))
        {
            Console.WriteLine("ID               : {0}", fund.id);
            Console.WriteLine("description      : {0}", fund.description);
            Console.WriteLine("GL code          : {0}", fund.GLCode);
            Console.WriteLine(" vat.id          : {0}", fund.vat.id);
            Console.WriteLine(" vat.description : {0}", fund.vat.description);
            Console.WriteLine(" vat.rate        : {0}", fund.vat.rate);
            Console.WriteLine();
        }
    }
}

}

12 May 2011 09:59 AM

Leave a comment

Name (required)
Email (required, not shown, for gravatar)
Website (optional)
Your Message
Leave these blank: