Bug in .NET Framework - SqlTypes - Stuart Gunter
in

dotnet.org.za

South African .NET Developer Portal

This Blog

Syndication

News


Get Firefox!
<!-- Begin Nedstat Basic code --> <!-- Title: StuartGunter --> <!-- URL: http://dotnet.org.za/stuartg/ --> <!-- End Nedstat Basic code -->

Stuart Gunter

There's too much!

Bug in .NET Framework - SqlTypes

Haven't blogged in a long time, but thought I'd break the silence with a little bug I found in the .NET Framework 1.1. I stand to be corrected on this, but I think a bug exists in the conversion from SqlDecimal to SqlInt32. To demonstrate, create a WinForms app and add two buttons. Use the following code for their click events:

private void button1_Click(object sender, System.EventArgs e)
{
try
{
SqlDecimal sqlDec = new SqlDecimal(decimal.Parse("20,000.50"));
int intValue = sqlDec.ToSqlInt32().Value;
MessageBox.Show(intValue.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

private void button2_Click(object sender, System.EventArgs e)
{
try
{
SqlDecimal sqlDec = new SqlDecimal(decimal.Parse("20,000.50"));
decimal dec = sqlDec.Value;
int intValue = (int)dec;
MessageBox.Show(intValue.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Now, I would expect both of these to return the same value of “20000” in the MessageBox, but they don't! It seems that the SqlDecimal conversion to SqlInt32 completely disregards the decimal point and returns the whole value as an int. In other words “2000.50” will convert to “200050” and “200.5000” will convert to “2005000”. I think this is wrong, as a conversion from SqlDecimal to SqlInt32 should truncate the decimal value to make it a whole number.

Any thoughts????

PS... I called Microsoft PSS and was told they don't support free downloads, including the .NET Framework. I've taken this up a few levels and will let you all know what happens!

Published Feb 11 2005, 01:47 PM by stuartg
Filed under:

Comments

 

Senkwe said:

Interesting. I'd never hit that because I'd always do the conversion as follows...

SqlInt32 intValue = (SqlInt32)sqlDec.Value;

Looks like a legit bug tho.
February 11, 2005 2:30 PM
 

Justin Lovell said:

It depends how one looks at it. By logics right in terms of the memory buffers, decimals should be dropped.

However, logically on a data centric level, it is correct. If you are *converting* the datatype to a different type, you would want to preserve the data after the decimal points. If you want to drop it completely then *casting* it makes sense (in the data centric level). Follow my thought pattern?
February 11, 2005 7:24 PM
 

Mongo-Matty said:

>>"I called Microsoft PSS and was told they don't support free downloads, including the .NET Framework"
Microsft doesnt support .NET wtf?
February 11, 2005 9:07 PM
 

Stuart Gunter said:

Hey...

In response to Justin>>>
Sorry, I don't follow your thought pattern at all. In any means of converting or casting (two words with the same underlying meaning), the decimal points should be dropped. There should be no confusion. An int cannot have decimal places, so they must be dropped. If you were to do the equivalent function in T-SQL, the result would be correct:

CAST(20.50 AS INT) will always be 20.

And you're trying to view "converting" and "casting" as two different things. They're not. They're exactly the same concept.


In response to Mongo-Matty>>>
Yep! That's what I thought! I'm *pretty sure* the support guy was completely confused (in fact, I hope so). A lot of major organisations are migrating to .NET, and would very quickly change their minds if they heard it wasn't supported by MS!

Like I said, I've emailed people further up the food chain at MS SA and will post the resolution to this problem if/when it comes.
February 11, 2005 9:57 PM
 

Justin Lovell said:

The similiarity of converting and casting is to input a certain data type and output the expected data type. The difference is how they go about doing that. Let's take it in an English context first...

You have a value of 5.3 tons. I tell you to convert that into an integer value without losing information. The answer? 5 300kg. Ok, that was not a problem! The process that you took was that you multiplied that to an equivalence.

Similiarily, I tell you to get the integer value out of 5.3 tons. I'm not telling you to preserve the data and nor are you allowed use another unit. That by definition, is called casting.

Just remember that when people designed these processes/compilers/languages/ect., they tried to replicate the English definition; they didn't declare two different terms and said that they can be used interchangably.
February 12, 2005 10:28 AM
 

Roaan Vos said:

There is a huge difference between converting and casting.
Casting takes what's in memory and pretends that its a different type. Converting takes what's in memory, and tries to create the required data type.

As an example, let's say we are dealing with the string "a".
In memory it is stored as "61" (using hex)
If we cast it to int, we'll get the value "61" for the value of the int.
However, should we try to convert it, it will fail because there is no way we can convert "a" to an int ;)

As another example, lets use the STRING "5".
In memory it will be stored as "35" (using hex)
If we cast it to an int, we will get a value of "35" (again using hex).
However, if we convert it, the int value again would be "5"
February 12, 2005 11:13 AM
 

Stuart Gunter said:

Yes... those are valid points, but we're not talking about hex, nor are we talking about units of measurement.

We're simply talking about decimal and int. There is no unit of measurement (e.g. tons) to be applied, and the .NET Framework should not assume to know what I want to do with it.

Both your arguments have very good merit, but they're different arguments to what we're talking about here.

Whether "converting" or "casting", the SqlInt32 representation of the SqlDecimal should be the value of the SqlDecimal before the decimal point. There's nothing more to it than that!
February 12, 2005 1:40 PM
 

Ernst Kuschke said:

The *definition* of casting and the *definition* of converting are not the same.
That said, it is certainly strange to find that the "logocal value" is different after the convert!
Think about it, all the convert does is to convert the *structure* of the SqlDecimal to an SqlInt32, IOW the data in the structure remains. It might be misleading though.
February 12, 2005 2:18 PM
 

Senkwe said:

Sorry guys, but thats a bug plain and simple. The documentation says the return value of a call to SqlDecimal.ToSqlInt32 is...

A SqlInt32 structure with the same value as this instance of SqlDecimal.

It would have helped though if they'd written the word "value" as "Value" in bold, to indicate that the "Value" property of SqlDecimal is what is being converted.
February 12, 2005 3:18 PM
 

Justin Lovell said:

Roaan and I were merely trying to get our point that leads onto the final one... which you are interested in ;-). Essentially, the keyword being for the converting process: preservation.

Yes, the documentation is misleading. According to the documentation Stuart has indeed found a bug. However, can one consider it a misprint? I think it is a misprint because we have already discussed the logic behind the casting and converting. Which, IMHO, MS will find that critical that their documentation is misleading :-P (seriously; no sarcasim there).
February 12, 2005 10:59 PM
 

ahmeds said:

I think this was logged with PSS and has been reported as a bug.
Stuart: can you confirm
February 16, 2005 12:25 PM
 

Stuart Gunter said:

Just a little feedback on this...

Yep, Ahmed is correct. I logged it with PSS and they've confirmed it is a bug. According to the response from MS UK, the fix will be available in VS 2005. I'm not sure if that means it won't be available for .NET 1.1, so if anyone is not likely to move to .NET 1.1 you may want to confirm this.

In the meantime, it's very easy to avoid. Just cast directly to int: "(int)sqlDec".
February 16, 2005 12:36 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Powered by Community Server (Commercial Edition), by Telligent Systems