0

I am trying to convert a byte received from a database query.

EF Core returns nullable tinyint as byte? and I need to convert it to decimal.

Is there any way to convert it OnModelCreating with model builder in the DbContext?

I am not very familiar with EF Core. So far I only managed to do this - after I already got my object in handler:

decimal? newDecimal = Convert.ToDecimal(BitConverter.ToDouble(AddByteToArray(priceByte), 0)));

private static byte[] AddByteToArray(byte? newByte)
{
    if (newByte != null)
    {
        if(newByte == 0)
        {
            return Enumerable.Repeat((byte)0x0, 8).ToArray();
        }

        byte[] bArray = new byte[1];
        // Not sure how to convert a non null and byte > 0 to byte[]?? As double requires byte[] while the tinyint return byte from the database

        return bArray;
    }

    return null;
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
nickornotto
  • 1,946
  • 4
  • 36
  • 68
  • 2
    I have to say I'm flabbergasted as to how the answer isn't obvious. You aren't converting anything. Just put that one byte in the array! – siride Jan 05 '22 at 14:54
  • I just tried initially `Convert.ToDecimal` and it didn't worked. – nickornotto Jan 05 '22 at 15:18
  • That's probably because that method takes a regular byte and not a nullable byte. But you can address that by checking for null before calling and then casting to a non-nullable byte. This is a reminder that you should take time to understand how types work in C#. It sounds like you are just trying things and hoping something works. That's a frustrating way to program – siride Jan 05 '22 at 15:24
  • I rather understand types. I never worked with bytes really before. – nickornotto Jan 05 '22 at 15:32
  • I tried Convert.toDecimal() onmodelcreating in db context so it was more tricky. Also I tried `modelBuilder .Entity() .Property(e => e.Price) .HasConversion( v => v != null ? (decimal)v : null;` before and it didn't worked so yeah probably that confused me even more. – nickornotto Jan 05 '22 at 15:33
  • The the problem is probably elsewhere. – siride Jan 05 '22 at 15:47
  • When you say it didn't work, what didn't work? Where is the code where it is failing? – siride Jan 05 '22 at 17:31
  • Take a look here as well: https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions?tabs=data-annotations#built-in-converters. There is probably a built-in conversion between two numbers. – siride Jan 05 '22 at 17:33
  • I figured out why it was erroring, I am just saying this is what confused me. Thanks – nickornotto Jan 05 '22 at 19:18
  • Can you post your solution as an answer? That way other people who might have the same problem in the future can reference it. – siride Jan 05 '22 at 20:27

2 Answers2

3

I think you are getting a little confused by the types here. The DB returns a byte? for a tinyint because a tinyint has only 8 bits of data. But otherwise it is an integer. If you want to convert it to a decimal, you would use the same mechanism as you would to convert an int or a long to a decimal: cast it. You do not want to convert a byte array to a decimal as that will try to interpret the data in the array as a binary representation of a decimal (see my last paragraph). So this code should suffice to do the conversion.

decimal? d = newByte == null ? null : (decimal)newByte; 

See that such a conversion is possible here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/numeric-conversions

Note the remarks section here that indicates we are dealing with a binary representation of the number, where care must be taken in dealing with endianness, etc.

https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter?view=net-6.0#remarks

Basically, numbers larger than a byte are technically stored as an array of bytes (since all memory is byte addressable in x86) but the interpration of those bytes into a number depends on the type of the number. For floating point numbers especially the structure of data inside the byte array is complex, broken into fields that represent the base, exponent and sign. And those are not always interpreted in a straightforward way. If you just give a byte array with 27 as the first byte, you don't know where that ends up in the several fields that make up the binary representation of a double. It may well work, but probably not.

siride
  • 200,666
  • 4
  • 41
  • 62
0

Instead of

byte[] bArray = new byte[1];

You can use

byte[] bArray = {(byte)newByte};
R44
  • 153
  • 1
  • 9
  • No, I can't so that. I already tried. In your case the byte array has only 1 item, while normally it is 8. The solution you suggested returns: `System.Private.CoreLib: Destination array is not long enough to copy all the items in the collection. Check array index and length. (Parameter 'value').` on converting to double: `BitConverter.ToDouble(bytesArray, 0);` – nickornotto Jan 05 '22 at 15:18