1

I'm looking for a way to change the default implementation of ITypeMap used by Dapper.

The database I am working on uses underscores in all the column names. For example "COLUMN_NAME". I don't want to have my POCO classes use property names with underscores, I'd rather use C# conventions for naming properties on my POCO classes. I also, dont want to have to write long select lists of "COLUMN_NAME AS ColumnName", or even give up the ability to do "SELECT * FROM ..".

I've found that Dapper allows me to write my own ITypeMap, which I have done and it works great! For my case I can write one mapper that will work for any select statement -- it just simply maps column names to property names with the underscores removed. However, because I have my own implementation of ITypeMap I must make a call to SqlMapper.SetTypeMap() at least one time for each POCO type. One of the things I like about Dapper is that there are no setup calls required at all when you use the default mapper. I am desperately trying to hold on to that experience as much as possible, while using the custom ITypeMap.

So instead of the elegant:

connection.Query<Animal>("select..");

I have:

SqlMapper.SetTypeMap(typeof(Animal), new TypeMap<Animal>());
connection.Query<Animal>("select..");

There is even more code when you start keeping track of which types have already been registered with SetTypeMap().

The best solution I have come up with so far is to wrap all the overrides of SqlMapper.Query(). In the wrapped methods I can check and call SetTypeMap() before calling SqlMapper.Query().

Something like this:

public static class DapperWrapper
{
    private static List<Type> _knownTypes = new List<Type>();

    public static IEnumerable<T> Query2<T>(this IDbConnection cnn, string sql, ...);
    {
        Setup<T>();

        return cnn.Query<T>(sql, ...);            
    }

    private static void Setup<T>()
    {
        Type type = typeof(T);

        if (!_knownTypes.Contains(type))
        {
            SqlMapper.SetTypeMap(type, new TypeMap<T>());
            _knownTypes.Add(type);
        }
    }
}

This gets me back to where I want to be:

connection.Query2<Animal>("select..");

Is there a better way of doing this? It seems like DapperExtensions has something like this in the AutoMapper, but it is not clear to me if that works with SqlMapper.Query().

Mike Hixson
  • 5,071
  • 1
  • 19
  • 24
  • What's wrong with settings each type map at application startup? When you want something different than a default implementation, you usually always end up with configuring that somewhere. Just put the code at `Application_Start` in the `Global.asax`. – Henk Mollema Apr 28 '14 at 19:31
  • I'm trying to avoid having any setup code, like the when using Dapper's default conventions. I literally have 100's of differnt types that I need to setup if I did it this way. Basically, I want to be able define my own convention once. I don't really need to customize each POCOs mapping individually. – Mike Hixson May 02 '14 at 21:22

2 Answers2

2
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;

https://stackoverflow.com/a/34536829/1315626

Community
  • 1
  • 1
scw
  • 5,450
  • 8
  • 36
  • 49
1

It's been a while, but I've been busy with developing a small Dapper extension, allowing you to configure mappings between property names and database column names. Name transformations (ColumnName -> COLUMN_NAME for example) are supported too.

You can find it here: https://github.com/HenkMollema/Dapper-FluentMap - there is also a NuGet package available. Let me know if it helps, suggestions/bugs are welcome.

Henk Mollema
  • 44,194
  • 12
  • 93
  • 104
  • I'm testing this extension now. It appears to be the best way yet to handle mappings without having to markup POCOs with attributes. – Michael Silver Nov 24 '14 at 08:18