Eiketsu
Eiketsu

Reputation: 203

Using SqlCommand with C# Variables

This is probably a somewhat remedial question, but I'm currently looking to update our database with content from an XML file created in and run through Visual Studio, and I'm fairly certain of what my mistake is, but not how to correct it. Working with Fields field0-field12, this is what I have for each of them.

string strField0; //strField0 - strField12
var doc = XDocument.Load("serializer.xml");

foreach (var xe in doc.Root.Elements("UserReportPreviewListDto"))
{
    XElement field0 = xe.Element("Field0");
    ConvertField(xe, "Field0", TranslateValueField);
    if (field0 != null)
    {
        strField0 = field0.Value;
    }
}
//strField0 - strField12

Below, I call the SqlConnection and SqlCommand thusly.

SqlConnection conn = new SqlConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string update =
    "INSERT INTO [dbo].[TABLE] ([Code], [Description], [SendEmail], [Type], [CustomForeColor], Inactive], [ModifiedDate], [CreatedDate], [ModifiedById], [CreatedById], [StartDate], [EndDate])
    VALUES (strField1, strField2, strField3, strField4, strField5, strField6, strField7, strField8, strField9, strField10, strField11, strField12)";
SqlCommand upd = new SqlCommand(update, conn);
conn.Open();
upd.ExecuteNonQuery();

I'm sure my mistake is in trying to use variables declared in Visual Studio in the Values field of that SQL statement, but I'm not quite sure of what the best workaround for that would be. Additionally, when it comes time to call SqlCommand upd, I'm not sure I'm doing that properly with upd.ExecuteNonQuery();.

I hope I'm clear on what I'm asking for with this. If not, please let me know. Any kind of assistance would be greatly appreciated.

Upvotes: 1

Views: 1551

Answers (3)

Steve
Steve

Reputation: 216353

You need a parameterized query like this

string update = @"INSERT INTO [dbo].[TABLE] ([Code], [Description], [SendEmail], 
                  [Type], [CustomForeColor], [Inactive], [ModifiedDate], [CreatedDate], 
                  [ModifiedById], [CreatedById], [StartDate], [EndDate])
                  VALUES (@code, @description, @sendemail, @type, @forecol, @inactive,
                          @moddate, @createdate,@modby, @createby,@start, @end)";

string conString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using(SqlConnection conn = new SqlConnection(conString))
using(SqlCommand cmd = new SqlCommand(update, conn))
{
    conn.Open();
    cmd.Parameters.Add(new SqlParameter
    { 
        ParameterName = "@code", 
        SqlDbType=SqlDbType.NVarChar, 
        Size=25,  // or whatever size you have for this field in the table 
        Value = strField1
    });
    cmd.Parameters.Add(new SqlParameter
    { 
        ParameterName = "@description", 
        SqlDbType=SqlDbType.NVarChar, 
        Size=255, // Same as before, the size should be equal to the field length on the table
        Value = strField2
    });
    .... and so on for the other parameters ....
    upd.ExecuteNonQuery();
}

I stopped to add parameters to the collection just after two examples, but you need to add the other parameters for every parameter placeholder present in the query. (The @xxxx) and most important; you need to specify the exact data type expected by the underlying table.

For example, the StartDate field is probably a datetime field and thus its parameter should be defined to be of SqlDbType.DateTime, something like this

cmd.Parameters.Add(new SqlParameter
{ 
     ParameterName = "@start", 
     SqlDbType=SqlDbType.DateTime, 
     Value = Convert.ToDateTime(strField11)
});

Notice that for parameters of type NVarChar is important to define the max size of the string passed. This allows the query optimizer of sqlserver to store the execution plan and reuse it if you call it again with the same parameter sizes. This is an interesting article about it.

Upvotes: 2

Tim Schmelter
Tim Schmelter

Reputation: 460288

You can't use the C# variables in a string literal, they won't be detected and interpreted as a column because you have not wrapped them in apostrophes like: 'strField1'. However, you should use sql-parameters anyway, most important because it prevents sql-injection.

string update = @"INSERT INTO [dbo].[TABLE] (
                    [Code], [Description], [SendEmail], 
                    [Type], [CustomForeColor], [Inactive], [ModifiedDate], [CreatedDate], 
                    [ModifiedById], [CreatedById], [StartDate], [EndDate])
                  VALUES (@Code, @Description, @SendEmail,@Type, @CustomForeColor, @Inactive,
                    @ModifiedDate, @CreatedDate, @ModifiedById, @CreatedById, @StartDate, @EndDate)";
SqlCommand upd = new SqlCommand(update, conn);
upd.Parameters.Add("@Code", SqlDbType.VarChar).Value = strField1;
upd.Parameters.Add("@Description", SqlDbType.VarChar).Value = strField2;
upd.Parameters.Add("@SendEmail", SqlDbType.Bit).Value = boolField;
// and so on ....
conn.Open();
upd.ExecuteNonQuery();

Use the correct types, so for example instead of passing always strings pass a DateTime for a datetime column and a bool to a bit column(that's why i've used boolField). If you need to convert them you can use the appropriate methods, for example int.Parse or DateTime.Parse.

Upvotes: 1

fly_ua
fly_ua

Reputation: 1054

You have to conver it to paramters liek that

string update = "INSERT INTO [dbo].[TABLE] ([Code], [Description], [SendEmail]....)
    VALUES (@strField1, @strField2, @strField3, ..";
SqlCommand upd = new SqlCommand(update, conn);
upd.Parameters.AddWithValue("@strField1", "1"); 
   ....

Upvotes: 1

Related Questions