2

In my C# app I am reading numeric data from my MySQL table. After that, I am searching for a minimal euclidean distance (between table row and an average tuple).

I am reading values from MySQL table into double variables (f1 to f8 and one int variable). I am getting this error on the first line, where I am putting the reader's result into f1. However, when I do random computation after reading my values for example (f1+f8), it returns right/exact result. So why does C# have a problem with the input string?

Here is my code:

for (int k = 1; k <= pocet; k++)
{
    string queryCompare = " SELECT F1 AS Fe1, F2 AS Fe2, F3 AS Fe3, F4 AS Fe4, F5 AS Fe5, F6 AS Fe6, F7 AS Fe7, F8 AS Fe8, cluster FROM features WHERE ID=" + k;
    MySqlCommand cmdCompare = new MySqlCommand(queryCompare, conect);
    readerCompare = cmdCompare.ExecuteReader();
    readerCompare.Read();
    //  MessageBox.Show("OK");
    double f1 = Convert.ToDouble(readerCompare["Fe1"].ToString());  // EXCEPTION HERE
    double f2 = Convert.ToDouble(readerCompare["Fe2"].ToString());
    double f3 = Convert.ToDouble(readerCompare["Fe3"].ToString());
    double f4 = Convert.ToDouble(readerCompare["Fe4"].ToString());
    double f5 = Convert.ToDouble(readerCompare["Fe5"].ToString());
    double f6 = Convert.ToDouble(readerCompare["Fe6"].ToString());
    double f7 = Convert.ToDouble(readerCompare["Fe7"].ToString());
    string f88 = readerCompare["Fe8"].ToString();
    double f8 = Convert.ToDouble(f88, CultureInfo.InvariantCulture);
    int cluster = Convert.ToInt32(readerCompare["cluster"].ToString());

    readerCompare.Close();
    //  MessageBox.Show((f1+f8).ToString());

    switch (cluster)
    {
        case 1:
            euklDist = (double)Math.Sqrt(
                                        Math.Pow(touple[0, 0] - f1, 2) + 
                                        Math.Pow(touple[0, 1] - f2, 2) + 
                                        Math.Pow(touple[0, 2] - f3, 2) + 
                                        Math.Pow(touple[0, 3] - f4, 2) + 
                                        Math.Pow(touple[0, 4] - f5, 2) + 
                                        Math.Pow(touple[0, 5] - f6, 2) + 
                                        Math.Pow(touple[0, 6] - f7, 2) + 
                                        Math.Pow(touple[0, 7] - f8, 2));

            if (euklDist < minCl1)
            {
                minCl1 = euklDist;
                idCl1 = k;
            }
            break;

        case 2:
            euklDist = (double)Math.Sqrt(
                                        Math.Pow(touple[1, 0] - f1, 2) +
                                        Math.Pow(touple[1, 1] - f2, 2) +
                                        Math.Pow(touple[1, 2] - f3, 2) + 
                                        Math.Pow(touple[1, 3] - f4, 2) + 
                                        Math.Pow(touple[1, 4] - f5, 2) +
                                        Math.Pow(touple[1, 5] - f6, 2) +
                                        Math.Pow(touple[1, 6] - f7, 2) +
                                        Math.Pow(touple[1, 7] - f8, 2));

            if (euklDist < minCl2)
            {
                minCl2 = euklDist;
                idCl2 = k;
            }
            break;

        case 3:
            euklDist = (double)Math.Sqrt(
                                        Math.Pow(touple[2, 0] - f1, 2) +
                                        Math.Pow(touple[2, 1] - f2, 2) + 
                                        Math.Pow(touple[2, 2] - f3, 2) +
                                        Math.Pow(touple[2, 3] - f4, 2) +
                                        Math.Pow(touple[2, 4] - f5, 2) + 
                                        Math.Pow(touple[2, 5] - f6, 2) + 
                                        Math.Pow(touple[2, 6] - f7, 2) + 
                                        Math.Pow(touple[2, 7] - f8, 2));

            if (euklDist < minCl3)
            {
                minCl3 = euklDist;
                idCl3 = k;
            }
            break;
    }
}

Records in my db are in this format:

  • from f1 to f7: xx,xxx
  • f8: xx.xxx

I know that f8 has decimal point instead of comma that is why I am using CultureInfo.InvariantCulture for f8.

11
  • 1
    What is the value of readerCompare["Fe1"].ToString() exactly? And what is your CurrentCulture? Commented May 9, 2014 at 11:08
  • @SonerGönül In column f1 I have approximately 400 values. Here are the first four: 91,08; 399,02; 445,76; 60,57. The same format is used in columns f2,f3,f4,f5,f6,f7. I dont really know why, but for f8 is is like this: 457.935; 452.72; etc. My current culture is sk-SK Commented May 9, 2014 at 11:40
  • @user2179427, is it failing on the first record? Commented May 9, 2014 at 11:45
  • @MichaelPerrenoud When the exception is thrown, the line where double f1 is, is highlited Commented May 9, 2014 at 11:46
  • @user2179427, the value of the row is exceptionally important here. What's the value of the row when it fails? Commented May 9, 2014 at 11:47

1 Answer 1

3

You don't need to update the null values, just do this:

Convert.ToDouble(readerCompare["Fe1"]);

The null will be handled by ToDouble and convert it to its default value; 0.

See, here is the ToDouble implementation you'd be using with the above code:

public static double ToDouble(object value)
{
  if (value != null)
    return ((IConvertible) value).ToDouble((IFormatProvider) null);
  else
    return 0.0;
}

UPDATE: alright if you also need to support empty strings then you'll have to change this code a little. First let's build an extension method. Create a new class in your solution and name it SystemExtensions, then paste in this code:

namespace System
{
    public static class SystemExtensions
    {
        public static string ToConvertibleDouble(this object input)
        {
            var s = input as string;
            if (string.IsNullOrEmpty(s.Trim())) { return null; }

            // this will also take care of the separator
            return s.Replace(".", ",");
        }
    }
}

and now let's use it:

Convert.ToDouble(readerCompare["Fe1"].ToConvertibleDouble());
Convert.ToDouble(readerCompare["Fe2"].ToConvertibleDouble());
...
Convert.ToDouble(readerCompare["Fe8"].ToConvertibleDouble());
Sign up to request clarification or add additional context in comments.

7 Comments

Same exception, but now the watch window says this: + Convert.ToDouble(readerCompare["Fe1"]); 'Convert.ToDouble(readerCompare["Fe1"])' threw an exception of type 'System.FormatException' double {System.FormatException}
@user2179427, you get the same exception after removing the ToString() call in the code?
@user2179427: what's the value of readerCompare["Fe1"] in the Watch window? Further, are you 100% sure this is the same row failing?
In watch window I have column "Name", where it says:"Convert.ToDouble(readerCompare["Fe1"]);", in column "Value" it says: "'Convert.ToDouble(readerCompar‌​e["Fe1"])' threw an exception of type 'System.FormatException'". So I dont really know if we are talking about the same window, or if I am understanding you correctly.
@user2179427, add a new watch expression and use this readerCompare["Fe1"] as the expression. Then tell me the value.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.