diff --git a/Dapper.sln b/Dapper.sln index 7a610ba6..a0e6bd76 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/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index f0c909fc..57d84edc 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, @@ -3905,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/global.json b/global.json index f3365c41..7da27634 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "8.0.100" + "version": "8.0.100", + "rollForward": "latestMajor" } } \ No newline at end of file diff --git a/tests/Dapper.Tests/MiscTests.cs b/tests/Dapper.Tests/MiscTests.cs index 9028919e..7f584856 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, diff --git a/tests/Dapper.Tests/TypeHandlerTests.cs b/tests/Dapper.Tests/TypeHandlerTests.cs index 2e754ca4..80c3292f 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] @@ -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; } }