Skip to content

Unsigned type mapping overflow #1164

Open
@Suprcode

Description

@Suprcode

When querying to a strongly type object which uses an unsigned short (ushort) you get an arithmetic overflow if the SQL value is greater than short.MaxValue (32767).

The SQL data type is an INT (best used for ushort values)

The mapping looks to be ignoring the fact its converting to an unsigned value which should allow twice the size (65535)

Errors
"Arithmetic operation resulted in an overflow."
Error parsing column 21 (XX=65535 - Int32)

Activity

mika76

mika76 commented on Jan 16, 2019

@mika76

Just hit this now with uint to bigint too

Suprcode

Suprcode commented on Jan 17, 2019

@Suprcode
Author

I fixed this by adding a custom handler for each of the unsigned types - though i think this should really be built in

public class UShortHandler : SqlMapper.TypeHandler<ushort>
    {
        private UShortHandler() {  }
        
        public static readonly SqlMapper.ITypeHandler Default = new UShortHandler();

        public override ushort Parse(object value)
        {
            return Convert.ToUInt16(value);
        }

        public override void SetValue(IDbDataParameter parameter, ushort value)
        {
            parameter.DbType = DbType.UInt16;
            parameter.Value = value;
        }
    }
mika76

mika76 commented on Jan 18, 2019

@mika76

Oooh that's clever, thanks 😄 👍

added this to the v2.0 milestone on Jan 27, 2019
NickCraver

NickCraver commented on Jan 27, 2019

@NickCraver
Member

Tagging this as 2.0 - I agree adding these handlers in the box in the next release seems correct on the surface. Going on the list.

ChristoWolf

ChristoWolf commented on Oct 13, 2021

@ChristoWolf

I encountered the same when trying to map (dap?) a BIGINT to a uint storage object property.
Dapper version: 2.0.78

rukpet

rukpet commented on Jul 1, 2022

@rukpet
Contributor

I think I found the root of the issue.
I encountered the same problem with mapping from SmallInt to byte.
It is failing only with values more than 127.

I suspect method SqlMapper.FlexibleConvertBoxedFromHeadOfStack uses wrong OpCodes mapping because in my case with byte the method uses OpCodes.Conv_Ovf_I1_Un so it is trying to convert SQL value to type with max value = 127 when byte have max value = 255 and as result we have OverflowException for values bigger that 127.
I think for conversion from SmallInt to byte the method should use OpCodes.Conv_Ovf_U1 or OpCodes.Conv_Ovf_U1_Un.
I see a similar problem with other unsigned types: UInt16, UInt32 and UInt64.

Dapper version: 2.0.4
Stack trace:

System.Data.DataException: Error parsing column 2 (PaymentMethodID=130 - Int16)
 ---> System.OverflowException: Arithmetic operation resulted in an overflow.
 at Deserialize0b626ef8-7dcd-4ff8-bb3d-3a4e1e08cf86(IDataReader )
 --- End of inner exception stack trace ---
 at Dapper.SqlMapper.ThrowDataException(Exception ex, Int32 index, IDataReader reader, Object value) in C:\projects\dapper\Dapper\SqlMapper.cs:line 3633
 at Deserialize0b626ef8-7dcd-4ff8-bb3d-3a4e1e08cf86(IDataReader )
 at Dapper.SqlMapper.QueryAsync[T](IDbConnection cnn, Type effectiveType, CommandDefinition command)
 at DevcodePaymentProcessor.DataAccessLayer.RequestSettingRepository.GetRequestSettingPaymentMethodsAsync(Nullable`1 requestSettingId)
 at DevcodePaymentProcessor.BusinessLogic.Commands.ReadPaymentProcessingSettingsCommand.ReadPaymentProcessingSettingsAsync()
 at DevcodePaymentProcessor.Handlers.GetPaymentProcessingSettingsHandler.GetPaymentProcessingSettingsAsync()
 at Grpc.Shared.Server.UnaryServerMethodInvoker`3.ResolvedInterceptorInvoker(TRequest resolvedRequest, ServerCallContext resolvedContext)
 at Grpc.Shared.Server.UnaryServerMethodInvoker`3.ResolvedInterceptorInvoker(TRequest resolvedRequest, ServerCallContext resolvedContext)
 at DevcodePaymentProcessor.Logging.DevcodeLoggingInterceptor.UnaryServerHandler[TRequest,TResponse](TRequest request, ServerCallContext context, UnaryServerMethod`2 continuation)

Mapping type:

public class ProcessorRequestSettingPaymentMethod
{
    public int RowID { get; set; }
    public int ProcessorRequestSettingID { get; set; }
    public byte PaymentMethodID { get; set; }
}
added a commit that references this issue on Jul 2, 2022
added a commit that references this issue on Nov 1, 2023
rukpet

rukpet commented on Nov 1, 2023

@rukpet
Contributor

@mgravell, sorry for tagging, but I see this issue is stuck. There is a solution (PR #1795) for the issue. Please check PR.

added a commit that references this issue on Jan 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @mika76@NickCraver@Suprcode@rukpet@ChristoWolf

        Issue actions

          Unsigned type mapping overflow · Issue #1164 · DapperLib/Dapper