Idan Arye
Idan Arye

Reputation: 12613

Can I define custom type mapping for parameters and fields in PetaPoco?

I'm currently trying to pick a C# ORM to use with my PostgreSQL database, and I'm interested in the micro-ORMs, since they allow me to better utilize the power of Postgres(and since full blown ORMs are hard to configure. While Dapper simply works, trying to deal with NHibernate has left a forehead shaped dent in my screen...)

Anyways, currently PetaPoco has the lead, but there is one feature I need and can't figure if it has(to be fair - I couldn't find it in the other ORMs either) - mapping of custom types.

My PostgreSQL database uses the hstore and Postgis extensions, which define custom types. I don't expect any ORM to support those types(it's hard enough to find one that supports PostgreSQL!) but I want to be able to provide my own mappers for them, so when I get them as columns or send them as parameters PetaPoco will automatically use my mappers.

Is this even possible? The closest I could find is IDbParameter support, but those are built-in types and I need to write mappers for extension types that are not part of the list...

Upvotes: 0

Views: 2445

Answers (1)

Idan Arye
Idan Arye

Reputation: 12613

Based on Schotime's comment, I came with half a solution - how to parse the hstore from the query results into the object. I'm leaving this question open in case someone wants to get the other solution.

I need to define my own mapper. Obviously I want to use PetaPoco's default mapping for regular types, so it's only natural to inherit PetaPoco.StandardMapper - but that won't work, because StandardMapper implements PetaPoco.IMapper's fields without the virtual attribute - so I can't override them(I can only overshadow them, but that's not really helping).

What I did instead was to implement IMapper directly, and delegate regular types to an instance of PetaPoco.IMapper:

public class MyMapper:PetaPoco.IMapper{
    private PetaPoco.StandardMapper standardMapper=new PetaPoco.StandardMapper();
    public PetaPoco.TableInfo GetTableInfo(Type pocoType){
        return standardMapper.GetTableInfo(pocoType);
    }
    public PetaPoco.ColumnInfo GetColumnInfo(PropertyInfo pocoProperty){
        return standardMapper.GetColumnInfo(pocoProperty);
    }
    public Func<object, object> GetFromDbConverter(PropertyInfo TargetProperty, Type SourceType){
        if(TargetProperty.PropertyType==typeof(HStore)){
            return (x)=>HStore.Create((string)x);
        }
        return standardMapper.GetFromDbConverter(TargetProperty,SourceType);
    }
    public Func<object, object> GetToDbConverter(PropertyInfo SourceProperty){
        if(SourceProperty.PropertyType==typeof(HStore)){
            return (x)=>((HStore)x).ToSqlString();
        }
        return standardMapper.GetToDbConverter(SourceProperty);
    }
}

The HStore object is constructed similarly to the one in Schotime's gist.

I also need to register the mapper:

PetaPoco.Mappers.Register(Assembly.GetAssembly(typeof(MainClass)),new MyMapper());
PetaPoco.Mappers.Register(typeof(HStore),new MyMapper());

Now, all of this works perfectly when I read from the query - but not when I write query parameters(even though I defined GetToDbConverter. It seems my mapper simply isn't called when I'm writing query parameters. Any idea how to do that?

Upvotes: 2

Related Questions