From 86c64a2eb1b7cd4ffd95255e458633237a67ee2e Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 6 Mar 2024 18:14:01 +0000 Subject: [PATCH 1/6] string and byte[] : add UseGetFieldValue to prevent problems with npgsql using global deserializer --- Dapper/SqlMapper.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index f0c909fce..02c467890 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -192,7 +192,9 @@ public TypeMapEntry(DbType dbType, TypeMapEntryFlags flags) public bool Equals(TypeMapEntry other) => other.DbType == DbType && other.Flags == Flags; public static readonly TypeMapEntry DoNotSet = new((DbType)(-2), TypeMapEntryFlags.None), - DecimalFieldValue = new(DbType.Decimal, TypeMapEntryFlags.SetType | TypeMapEntryFlags.UseGetFieldValue); + DecimalFieldValue = new(DbType.Decimal, TypeMapEntryFlags.SetType | TypeMapEntryFlags.UseGetFieldValue), + StringFieldValue = new(DbType.String, TypeMapEntryFlags.SetType | TypeMapEntryFlags.UseGetFieldValue), + BinaryFieldValue = new(DbType.Binary, TypeMapEntryFlags.SetType | TypeMapEntryFlags.UseGetFieldValue); public static implicit operator TypeMapEntry(DbType dbType) => new(dbType, TypeMapEntryFlags.SetType); @@ -214,13 +216,13 @@ static SqlMapper() [typeof(double)] = DbType.Double, [typeof(decimal)] = DbType.Decimal, [typeof(bool)] = DbType.Boolean, - [typeof(string)] = DbType.String, + [typeof(string)] = TypeMapEntry.StringFieldValue, [typeof(char)] = DbType.StringFixedLength, [typeof(Guid)] = DbType.Guid, [typeof(DateTime)] = TypeMapEntry.DoNotSet, [typeof(DateTimeOffset)] = DbType.DateTimeOffset, [typeof(TimeSpan)] = TypeMapEntry.DoNotSet, - [typeof(byte[])] = DbType.Binary, + [typeof(byte[])] = TypeMapEntry.BinaryFieldValue, [typeof(byte?)] = DbType.Byte, [typeof(sbyte?)] = DbType.SByte, [typeof(short?)] = DbType.Int16, From 10e2e7aa8ac41f3b7aa6d97c4fda99ac1dc256f8 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 6 Mar 2024 18:20:07 +0000 Subject: [PATCH 2/6] use 8.0.200 SDK --- Dapper.sln | 1 + global.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dapper.sln b/Dapper.sln index 7a610ba6a..a0e6bd769 100644 --- a/Dapper.sln +++ b/Dapper.sln @@ -15,6 +15,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution global.json = global.json docs\index.md = docs\index.md License.txt = License.txt + .github\workflows\main.yml = .github\workflows\main.yml nuget.config = nuget.config Readme.md = Readme.md version.json = version.json diff --git a/global.json b/global.json index f3365c418..e2138e083 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.100" + "version": "8.0.200" } } \ No newline at end of file From 83cc044438fb200bca0c0bec9456e8e50dfa30f1 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 6 Mar 2024 18:28:25 +0000 Subject: [PATCH 3/6] prefer rollforward over bumping version --- global.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/global.json b/global.json index e2138e083..7da276347 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "8.0.200" + "version": "8.0.100", + "rollForward": "latestMajor" } } \ No newline at end of file From 77fdceb2f28d06f96e9e13eaac118c876ff7d8db Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 6 Mar 2024 18:44:11 +0000 Subject: [PATCH 4/6] switch to GetFieldValue changes some messaging in invalid cast scenarios; if anything, new version is clearer, so: fine --- Dapper/SqlMapper.cs | 6 +++++- tests/Dapper.Tests/TypeHandlerTests.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 02c467890..57d84edc1 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -3907,7 +3907,11 @@ public static void ThrowDataException(Exception ex, int index, IDataReader reade } try { - if (value is null || value is DBNull) + if (value is null && ex is InvalidCastException) + { + formattedValue = "n/a - " + ex.Message; // provide some context + } + else if (value is null || value is DBNull) { formattedValue = ""; } diff --git a/tests/Dapper.Tests/TypeHandlerTests.cs b/tests/Dapper.Tests/TypeHandlerTests.cs index 2e754ca46..9dc83b5da 100644 --- a/tests/Dapper.Tests/TypeHandlerTests.cs +++ b/tests/Dapper.Tests/TypeHandlerTests.cs @@ -643,7 +643,7 @@ public void Issue149_TypeMismatch_SequentialAccess() { Guid guid = Guid.Parse("cf0ef7ac-b6fe-4e24-aeda-a2b45bb5654e"); var ex = Assert.ThrowsAny(() => connection.Query("select @guid as Id", new { guid }).First()); - Assert.Equal("Error parsing column 0 (Id=cf0ef7ac-b6fe-4e24-aeda-a2b45bb5654e - Object)", ex.Message); + Assert.Equal("Error parsing column 0 (Id=n/a - Unable to cast object of type 'System.Guid' to type 'System.String'.)", ex.Message); } public class Issue149_Person { public string? Id { get; set; } } From c8b2c8bfb62fe5867bdb7a3f2a9fd1fdfd0a5d0d Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 6 Mar 2024 18:53:44 +0000 Subject: [PATCH 5/6] test fixes --- tests/Dapper.Tests/MiscTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Dapper.Tests/MiscTests.cs b/tests/Dapper.Tests/MiscTests.cs index 9028919ea..7f5848565 100644 --- a/tests/Dapper.Tests/MiscTests.cs +++ b/tests/Dapper.Tests/MiscTests.cs @@ -265,7 +265,7 @@ static async Task TestExceptionsAsync(DbConnection connection, string sql, st await TestExceptionsAsync( connection, "Select null as Foo", - "Error parsing column 0 (Foo=)"); + "Error parsing column 0 (Foo=n/a - Null object cannot be converted to a value type.)"); // Incompatible value throws (testing unnamed column bits here too) await TestExceptionsAsync( connection, From 0cb67faed66c66d716ad7dfc3c7d1ddf0d44c1ad Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Wed, 6 Mar 2024 19:02:24 +0000 Subject: [PATCH 6/6] more fixups --- tests/Dapper.Tests/TypeHandlerTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Dapper.Tests/TypeHandlerTests.cs b/tests/Dapper.Tests/TypeHandlerTests.cs index 9dc83b5da..80c3292ff 100644 --- a/tests/Dapper.Tests/TypeHandlerTests.cs +++ b/tests/Dapper.Tests/TypeHandlerTests.cs @@ -28,12 +28,12 @@ public void TestChangingDefaultStringTypeMappingToAnsiString() SqlMapper.PurgeQueryCache(); - SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString); // Change Default String Handling to AnsiString + SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString, true); // Change Default String Handling to AnsiString var result02 = connection.Query(sql, param).FirstOrDefault(); Assert.Equal("varchar", result02); SqlMapper.PurgeQueryCache(); - SqlMapper.AddTypeMap(typeof(string), DbType.String); // Restore Default to Unicode String + SqlMapper.AddTypeMap(typeof(string), DbType.String, true); // Restore Default to Unicode String } [Fact] @@ -47,12 +47,12 @@ public void TestChangingDefaultStringTypeMappingToAnsiStringFirstOrDefault() SqlMapper.PurgeQueryCache(); - SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString); // Change Default String Handling to AnsiString + SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString, true); // Change Default String Handling to AnsiString var result02 = connection.QueryFirstOrDefault(sql, param); Assert.Equal("varchar", result02); SqlMapper.PurgeQueryCache(); - SqlMapper.AddTypeMap(typeof(string), DbType.String); // Restore Default to Unicode String + SqlMapper.AddTypeMap(typeof(string), DbType.String, true); // Restore Default to Unicode String } [Fact]