DapperLib / DapperLib/Dapper

Bug: TypeHandler.Parse not called with Scalar* methods

Open
#1,218 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
18.4k
Forks
3.7k
Avg merge
5h 8m
Merged PRs (30d)
1

Description

When you add a custom type handler, it will not be called with Scalar* methods. In the following sample for PostgreSQL I expect to get the same result in both calls, but my custom type handler will only be called once:

using Dapper;
using Npgsql;
using System;
using System.Data;
using System.Threading.Tasks;

namespace DapperBug
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlMapper.RemoveTypeMap(typeof(DateTime));
            SqlMapper.AddTypeHandler(typeof(DateTime), new DateTimeHandler());

            var sql = $@"DROP TABLE IF EXISTS DateTimeTest;
                         CREATE TEMPORARY TABLE DateTimeTest (DateTime timestamp(6) NOT NULL PRIMARY KEY);
                         INSERT INTO DateTimeTest (DateTime) VALUES (@DateTime);
                         SELECT * FROM DateTimeTest LIMIT 1;";

            using (var conn = new NpgsqlConnection("...[connection string]..."))
            {
                conn.Open();
                var tran = conn.BeginTransaction();

                var parameters = new { DateTime = DateTime.UtcNow };

                var result1 = conn.ExecuteScalar<DateTime>(sql, parameters);
                var result2 = conn.QuerySingle<Sample>(sql, parameters);

                if (result1.Kind != result2.DateTime.Kind)
                {
                    throw new Exception("Both dates are not equal");
                }

                tran.Rollback();
            }
        }
    }

    public class Sample
    {
        public DateTime DateTime { get; set; }
    }

    public class DateTimeHandler : SqlMapper.TypeHandler<DateTime>
    {
        public override void SetValue(IDbDataParameter parameter, DateTime value)
        {
            parameter.Value = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second, value.Kind);
            parameter.DbType = DbType.DateTime;
        }

        public override DateTime Parse(object value)
        {
            return DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
        }
    }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by inspecting the ExecuteScalar and QuerySingle entry points and how SqlMapper.TypeHandler.Parse is reached. Reproduce the PostgreSQL example, then add a regression test showing consistent handler invocation for both methods; done means both results receive the handler's DateTimeKind behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, postgresql
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.