From 49b74fc985e291af379907c9720b9f9ea0536396 Mon Sep 17 00:00:00 2001 From: "Dailey, Alaric" Date: Sat, 24 Oct 2026 08:02:24 -0500 Subject: [PATCH] Prioritize custom handlers over type maps --- Dapper/SqlMapper.cs | 8 ++-- Directory.Packages.props | 1 + tests/Dapper.Tests/Dapper.Tests.csproj | 1 + tests/Dapper.Tests/FakeDbTests.Issue1298.cs | 46 +++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 tests/Dapper.Tests/FakeDbTests.Issue1298.cs diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 8f3956cab..2297e31d4 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -473,6 +473,10 @@ public static void SetDbType(IDataParameter parameter, object value) } type = Enum.GetUnderlyingType(type); } + if (typeHandlers.TryGetValue(type, out handler)) + { + return DbType.Object; + } if (typeMap.TryGetValue(type, out var mapEntry)) { if ((mapEntry.Flags & TypeMapEntryFlags.SetType) == 0) @@ -485,10 +489,6 @@ public static void SetDbType(IDataParameter parameter, object value) { return DbType.Binary; } - if (typeHandlers.TryGetValue(type, out handler)) - { - return DbType.Object; - } if (typeof(IEnumerable).IsAssignableFrom(type)) { // auto-detect things like IEnumerable as a family diff --git a/Directory.Packages.props b/Directory.Packages.props index 2f91a3cca..b1e42ba41 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -38,6 +38,7 @@ + diff --git a/tests/Dapper.Tests/Dapper.Tests.csproj b/tests/Dapper.Tests/Dapper.Tests.csproj index 93b498618..e9eab6b88 100644 --- a/tests/Dapper.Tests/Dapper.Tests.csproj +++ b/tests/Dapper.Tests/Dapper.Tests.csproj @@ -32,6 +32,7 @@ + diff --git a/tests/Dapper.Tests/FakeDbTests.Issue1298.cs b/tests/Dapper.Tests/FakeDbTests.Issue1298.cs new file mode 100644 index 000000000..5333629c0 --- /dev/null +++ b/tests/Dapper.Tests/FakeDbTests.Issue1298.cs @@ -0,0 +1,46 @@ +#if !NET481 +using System.Data; +using pengdows.crud.fakeDb; +using Xunit; + +namespace Dapper.Tests; + +public sealed class FakeDbIssue1298Tests +{ + [Fact] + public void CustomHandlerOverridesBuiltInTypeMap() + { + SqlMapper.ResetTypeHandlers(); + var handler = new StringHandler(); + SqlMapper.AddTypeHandler(handler); + try + { + using var connection = new fakeDbConnection(new FakeDataStore()); + connection.EnqueueNonQueryResult(1); + connection.Open(); + + connection.Execute("select @value", new { value = "hello" }); + + Assert.True(handler.Called); + } + finally + { + SqlMapper.ResetTypeHandlers(); + } + } + + private sealed class StringHandler : SqlMapper.TypeHandler + { + public bool Called { get; private set; } + + public override string Parse(object value) => (string)value; + + public override void SetValue(IDbDataParameter parameter, string? value) + { + Called = true; + parameter.DbType = DbType.String; + parameter.Value = value; + } + } +} +#endif