views:

1091

answers:

5

I'm having a problem when passing nulls to a ExecuteCommand() method using linq. My code is similar to the one that follows:

    public void InsertCostumer(string name, int age, string address)
    {
        List<object> myList = new List<object>();

        myList.Add(name);
        myList.Add(age);
        myList.Add(address);

        StringBuilder queryInsert = new StringBuilder();
        queryInsert.Append("insert into Customers(name, address) values ({0}, {1}, {2})");

        this.myDataContext.ExecuteCommand(queryInsert.ToString(), myList.ToArray());
    }

But, when a parameter is null (address, for instance), I get the following error: "A query parameter cannot be of type 'System.Object'."

The error doesn't occur if no parameters are null. I know the design in my example is a little poor, I just created a simplified example to focus on the problem. Any suggestions?

A: 

Does the insert value need to actually be a String "null" instead of a null object?

Joel Cochran
It is a null value. No string "null"
Samuel Carrijo
Just out of curiosity, just for debugging, I would make a string that has all the values populated and see what the formatted string value is prior to ExecuteCommand.
Joel Cochran
It works well for populated strings. Only the null value throws the unwanted exception
Samuel Carrijo
A: 

have you tried assigning a value to those that are null? Meaning (pseudo):

If address is null then address = "" or If age is < 0 then age = 0

then add it to myList

or you could always use a Ternary operator:

name = name.Length < 1 ? "" : name;
age = age < 1 ? Int32.MinValue : age;

then add it to myList

northpole
What if I have like 10 fields, or something like that. Must I validate them all. Also, my database accept null values, and I want to save them as null. I don't see using some other arbitrary value to replace null as a good practice
Samuel Carrijo
I usually only validate the ones that could be NULL, so yes, you might need to do them all. I agree with you, if you in fact want to preserve the NULL then you wouldn't want my approach. Also, I wouldn't call it an arbitrary value because it really is just the min value the object can have and not some random meaningless value.
northpole
What I'm trying to say is. Even if we take an empty string (or Int32.MinValue) and use it, there are other applications that save this as null (the customer didn't say his age, so it will be saved as null, considering every field is nullable). So, when explaining my DB to someone else, I'll say. Oh, if the customer doesn't provide his age, it will be null or Int32.MinValue, it depends on which application saved it (or the same for his address, which could be empty or null).Also, whoever reads this value will have a portion if (age == null || age == Int32.MinValue) :(
Samuel Carrijo
A: 

why not use nullable values?

public void InsertCostumer(string? name, int? age, string? address)
{
    List<object> myList = new List<object>();

    myList.Add(name.GetValueOrDefault());
    myList.Add(age.GetValueOrDefault());
    myList.Add(address.GetValueOrDefault());

    StringBuilder queryInsert = new StringBuilder();
    queryInsert.Append("insert into Customers(name, address) values ({0}, {1}, {2})");

    this.myDataContext.ExecuteCommand(queryInsert.ToString(), myList.ToArray());
}
tim
It doesn't work when they are null
Samuel Carrijo
ah of course - string is a reference type. oops.
tim
i guess ur stuck with extension methods for strings, and ints can't be null. Oops @ prev.static void Main(string[] args) { test(null); } public static string test(string tester) { return tester.ToDefaultedString(); } } public static class Test { public static string ToDefaultedString(this String test2) { if (test2 != null) { return test2.ToString(); } else { return string.Empty; } } }
tim
A: 

Hey Samuel

In .NET, a null/nothing string does not evaluate to an empty string, i.e. "". If you want "", then that has to be the value of the string, or if you want to represent null/nothing in SQL, you have to manually write out "NULL" if your .NET string is in fact null/nothing.

All the execute command does, is execute a SQL query, provide by you, as a String. it doesn't do anything else special in terms of that SQL string.

So, for the Execute Command to work, you have to pass in a valid SQL string, you have to manually construct the string correctly.

andy
+4  A: 

This is a known bug and Microsoft does not intend to fix it...

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=305114&amp;wa=wsignin1.0

The work around is to either:

  1. Drop into ADO.NET and execute the SQL Command directly
  2. Format the string you're executing yourself and call ExecuteCommand with an empty object array (new object[0])

The second isn't a good idea as it opens you up to SQL inject attacks, but its a quick hack.

Kevin Berridge