DapperLib / Dapper

Dapper - a simple object mapper for .Net
https://www.learndapper.com/
Other
17.44k stars 3.67k forks source link

Different TypeHandler for different database types #1668

Open rent-a-developer opened 3 years ago

rent-a-developer commented 3 years ago

Hi,

is there a way to tell Dapper to use specific TypeHandlers depending on the type of database (e.g. SQLite/SQL Server/MySQL/etc.) that is being queried?

My situation: I am using Dapper to query data from a SQLite db and a SQL Server db in the same application.

For SQLite I have implemented some custom TypeHandlers. For example I have a TypeHandler that converts System.DateTime values to strings and strings back to DateTimes.

This causes a problem now, when I use Dapper to query data from SQL Server. SQL Server (more precisely the SQL Server ADO.NET provider) already returns datetime values as instances of the System.DateTime type, but my (SQLite specific) TypeHandler expects date times values to be retrieved as strings from the database.

Now, I know I could examine the value returned from the database in my TypeHandler and act accordingly, but there are some downsides to this approach.

Ideally I would like Dapper to use one TypeHandler for SQLite and another for SQL Server.

Is this possible? Or is there maybe some way I can determine the database type from inside the TypeHandler?

NickCraver commented 3 years ago

There isn't a way to do this today, but is it a feature we'd support with the changes in vNext - the plan is to move these bits into a non-static DapperConfig and we'd allow this to be scoped and used in different areas. That should allow use cases like this, but it'll be a while until we get there.

rent-a-developer commented 3 years ago

Thank you very much @NickCraver! This is fantastic news!

The idea of having scoped settings is brilliant! I think I'll "borrow" it and implement it in my TypeHandler for the time being.

Something like:

class SQLiteScope : IDisposable
{
    public static Boolean IsActive { get; private set; }

    public SQLiteScope()
    {
        IsActive = true;
    }

    public void Dispose()
    {
        IsActive = false;
    }
}

class SQLiteTypeHandler : SqlMapper.ITypeHandler
{
    public void SetValue(IDbDataParameter parameter, Object value)
    {
        if (SQLiteScope.IsActive)
        {
            // Apply SQLite specific rules...
        }
        else
        {
            // Apply default rules...
        }
    }
}

...

using(new SQLiteScope())
{
    var items = sqliteConnection.Query<Item>("SELECT * FROM [Item]").ToList();
}
CesGan commented 2 weeks ago

Hello there. Are we expecting some development on this topic?