tags:

views:

134

answers:

6

Hey, my app parses numerous txt files in a directory that are almost all formatted identically, then inserts the values into columns of my sql db. However, there are a few files that the app has come across where a value is 'blank' instead of '0.0', so the application fails stating that it cannot convert that value to numeric.

Is there a way I could change the following code to say what says AND also add 'IF value is blank, then import 0.0 instead?

EDIT: The following code seems to get my pass my error, however now I have all columns showing as numbers. if it is text, it inputs "0" in its place...

string[] values = line.Split(new[] { ',' });

                                for (int i = 0; i < values.Length - 1; i++)
                                {

                                    SqlParameter param = insertCommand.Parameters[i];

                                    decimal value;
                                    if (values[i] == null || values[i] == "")
                                    {
                                        value = 0.000m;
                                    }
                                    else
                                    {
                                        if (!decimal.TryParse(values[i], out value))
                                        {

                                           // param.Value = decimal.TryParse(values[i], out value) ? value : 0;
                                            param.Value = values[i];
                                        }

                                    }
                                    param.Value = value;
                                } 
A: 

Doesn't decimal.TryParse return false when executed on an empty string?

edit

Here's the offending line:

param.Value = values[i];

The right hand side should be value, not values[i].

edit

The problem is that it executes param.Value = value; regardless. In other words, when it's not a number, you correctly assign values[i] to parm.Value, and then incorrect overwrite it with value, which is always 0 at that point.

Steven Sudit
I think there is something wrong with this statement? param.Value = decimal.TryParse(values[i], out value) ? value : 0;
jakesankey
@jake: I don't *see* anything wrong with it. And when I plugged it into VS, it worked exactly as expected: empty or null strings yielded a result of 0. What's going on here?
Steven Sudit
Man, I still can't figure it out! I have tried the above ideas and still get the same error. Somewhere in that code, the value 'null' or 'blank' is getting through and throwing the error. If there are any other ideas, please help.
jakesankey
@jake: Maybe the parameter is not of type decimal...
Steven Sudit
Parameter type confirmed. Decimal.... frustrating. Can't imagine what else to do. I am dangerously close to simply changing that column to varchar. Would that hurt anything?
jakesankey
@Jake: The reason not to just switch to varchar is that you'd be treating a problem you haven't diagnosed, so it might or might not work, and might or might not have side effects worse than the underlying cause.If all of your premises were true, the system would not be capable of behaving as it does. Therefore, you must test your premises, and that means adding extensive logging so that you can trace what *actually* happens.
Steven Sudit
I have added my complete code above. I have successfully imported over 2 million records into the db and it keeps failing on this same line that contains data,,data,data... Perhaps you can see something i am not seeing.
jakesankey
@Jake: See above for the answer.
Steven Sudit
Ok, so this gets me pass the errors but now my FeatType, FeatName, and Axis columns all return 0 the whole way down the db for new imports??? -- I updated the code in the orgininal question to show what mine looks like..
jakesankey
@Jake: See above for the next answer.
Steven Sudit
A: 

Try this:

decimal value;
if (values[i] == string.Empty || values[i] == "blank")
{
    value = 0.0m;
}
else
{
    if (!decimal.TryParse(values[i], out value))
    {
        // Error handling
    }
}

param.Value = value;
Mark Byers
same error.. I am lost. Unless I put the wrong code in the //error handling section.
jakesankey
@jakesankey: Perhaps your string is not blank, but contains something else like a single space. In the above code I left a section for error handling. If you do something useful here such as logging the value of `values[i]` that gives the error then you should be able to post the cause of the problem here and get a fix. Assuming that it's a space you could change `values[i] == string.Empty` to `values[i].Trim() == string.Empty`.
Mark Byers
That's a reasonable guess, but it looks like the cause was a simpler error than that.
Steven Sudit
A: 

If you were in SQL it would be IsNull() or Coalesce(), but in C# you'll just want to toss a ternary operater in place "?:" since decimal.TryParse should return false if it cannot parse, your second value would be 0.0

http://msdn.microsoft.com/en-us/library/ty67wk28(VS.80).aspx

iivel
A: 

I'm not a C# programmer, but I'd inspect values when you hit one of the blanks in the debugger, see what the type of the blank is, and test for that condition explicitly as you go through your for loop. For example, if it's null then just set that value to 0.0 in your loop.

John at CashCommons
any example code to help me out? I am still struggling with it.
jakesankey
A: 

Your problem is that the default value of decimal is 0m.

So:

decimal value;
if (values[i] == null || values[i] == "")
{
    value = 0.000m;
}
else
{
    if (!decimal.TryParse(values[i], out value))
    {
       // param.Value = decimal.TryParse(values[i], out value) ? value : 0;
       param.Value = values[i];
    }

    // value == 0m still!!! 
    // put debugger on this line and you can verify this:
    var testDecimalValue = value;
}

param.Value = value;

Pretty much guarantees that only numeric values or 0 (if the value is not numeric) will be set to the param.Value property.

Try changing your code to:

if (values[i] == null || values[i] == "")
{
    param.Value = 0.000m;
}
else
{
    decimal value;
    if (!decimal.TryParse(values[i], out value))
    {
       // param.Value = decimal.TryParse(values[i], out value) ? value : 0;
       param.Value = values[i];
    }
    else
    {
       param.Value = value;
    }
}
code4life
Thanks. This works, however it is much slower while parsing the files.
jakesankey
Can you breakpoint the code and see if it's the new logic, or the execution of the SQL? I suspect the SQL execution is the reason for the slowness (now that the parameters actually become meaningful to the query optimizer).
code4life
Thank you very much! The SQL connection on my server was just slow at the moment!
jakesankey
A: 

This looks like what you're looking for:

foreach (int i = 0; i < values.Length; i++)
{
    SqlParameter param = insertCmd.Parameters[i];
    if (string.IsNullOrEmpty(values[i]))
    {
        param.Value = new Decimal(0m);
    }
    else
    {
        decimal d = new Decimal(0m);
        if (decimal.TryParse(values[i], out d))
            param.Value = d;
        else
            param.Value = new Decimal(0m);
    }   
}

note that the problem with yours looks to be here:

if (!decimal.TryParse(values[i], out value))          
{            
    param.Value = values[i];          
}   

basically, you're saying "if the parse failed, then use the text the values array at i".

SnOrfus