-2

I am trying to insert data from dynamically generated textbox of gridview in the database. however, I am getting the exception of the CommandText property has not been initialized cmd.executeNonQuery();

private void InsertRecords(StringCollection sc)
{
    StringBuilder sb = new StringBuilder(string.Empty);
    string[] splitItems = null;
    const string sqlStatement = "INSERT INTO Ingredients_List (Ingredients1) VALUES";
    foreach (string item in sc)
    {
        if (item.Contains(","))
        {
            splitItems = item.Split(",".ToCharArray());
            sb.AppendFormat("{0}('{1}'); ", sqlStatement, splitItems[0]);
        }

    }
    //  conn.Open();
    using (SqlConnection connn = new SqlConnection(GetConnectionString()))

    {
        using (SqlCommand cmd = new SqlCommand(sb.ToString(), connn))
        {
            connn.Open();
            //      cmd.CommandType = CommandType.Text;
            cmd.ExecuteNonQuery();
            connn.Close();
        }
        // Page.ClientScript.RegisterClientScriptBlock(typeof(Page), "Script", "alert('Records Successfuly Saved!');", true);
    }
}
Chandan Kumar
  • 4,570
  • 4
  • 42
  • 62
Tanmay Parmar
  • 177
  • 1
  • 2
  • 14
  • what is sb.tostring() returning? – Baahubali Apr 01 '17 at 06:58
  • 1
    1) You're not appending the sqlStatement to the StringBuilder 2) Unless there's a , in the item, you won't insert it into the database. 3) Please use parameterized queries. It's safer. Your current method is wide open to SQL injection. – ProgrammingLlama Apr 01 '17 at 06:58
  • what i am trying to do is creating dynamic textbox onClick event and then saving data to the database. so how to use parameterized query for that? i am using this example http://www.c-sharpcorner.com/uploadfile/8c19e8/dynamically-adding-and-deleting-rows-in-gridview-and-saving/ – Tanmay Parmar Apr 01 '17 at 07:02
  • 1
    @john Your 1) doesn't look right. The `sb.AppendFormat` includes it, except for the case of your point 2). –  Apr 01 '17 at 07:02
  • @hvd Ah, my mistake. It must be 2) then. – ProgrammingLlama Apr 01 '17 at 07:03
  • Ditto what @john is saying about using a parameterized query. ESPECIALLY if you're going to be setting parameter values directly from user-entered text. – STLDev Apr 01 '17 at 07:05
  • First you aren't putting the `sqlStatement ` into the `StringBuilder` (Honestly I'd initilize the sb with that statement, not have it a separate variable) and you never check that you actually had anything in `sc` before you try to run the query. And I am not sure how your `sc` is supposed to work, since you are only ever adding the first value from the comma separated string in`item`. – Andrew Apr 01 '17 at 12:56

2 Answers2

2

Your problem is caused by the fact that you don't check if, after the loop, you have inserted anything in the StringBuilder. In case of no string with commas, then, the internal condition into the foreach statement, leaves the stringbuilder empty and the command will never have a proper command text.

The workaround should be simple like adding a test to see if there is some text inside the StringBuilder but I prefer to suggest you a different approach using a List<SqlParameter>

StringBuilder sb = new StringBuilder(string.Empty);
List<SqlParameter> prms = new List<SqlParameter>();
string[] splitItems = null;

// Base string for creating parameter placeholders dynamically
string sqlStatement = "INSERT INTO Ingredients_List (Ingredients1) VALUES (@p{0});";

int count = 1;
foreach (string item in sc)
{
    if (item.Contains(","))
    {
        splitItems = item.Split(',');

        // Parameter name created dynamically
        prms.Add(new SqlParameter($"@p{count}", SqlDbType.NVarChar) {Value=splitItems[0]});

        // Create the placeholder for the nth parameter
        sb.AppendFormat(sqlStatement, count);
    }
}

// Don't execute anything if there are no parameters (or stringbuilder empty)
if(prms.Count > 0)
{
    using (SqlConnection connn = new SqlConnection(GetConnectionString()))
    using (SqlCommand cmd = new SqlCommand(sb.ToString(), connn))
    {
        connn.Open();

        // Add all parameters together
        cmd.Parameters.AddRange(prms);
        cmd.ExecuteNonQuery();
    }
}
Steve
  • 213,761
  • 22
  • 232
  • 286
-1

You're not loading the first part of your query into the StringBuilder. Try this:

private void InsertRecords(StringCollection sc)
{
    const string sqlStatement = "INSERT INTO Ingredients_List (Ingredients1) VALUES";
    StringBuilder sb = new StringBuilder(sqlStatement);
    string[] splitItems = null;
    foreach (string item in sc)
    {
        if (item.Contains(","))
        {
            splitItems = item.Split(",".ToCharArray());
           sb.AppendFormat("{0}('{1}'); ", sqlStatement, splitItems[0]);
        }
    }
    //  conn.Open();
    using (SqlConnection connn = new SqlConnection(GetConnectionString()))
    {
        using (SqlCommand cmd = new SqlCommand(sb.ToString(), connn))
        {
            connn.Open();
            //      cmd.CommandType = CommandType.Text;
            cmd.ExecuteNonQuery();
            connn.Close();
        }
        // Page.ClientScript.RegisterClientScriptBlock(typeof(Page), "Script", "alert('Records Successfuly Saved!');", true);
    }
}

EDIT - I've built a test database and debugged the following code. It works for the test data I passed it.

    private void InsertRecords(StringCollection sc)
    {
        const string sqlStatement = "INSERT INTO Ingredients_List (Ingredients1) VALUES";
        StringBuilder sb = new StringBuilder();

        foreach (string item in sc)
        {
            if (item.Contains(","))
            {
                var splitItems = item.Split(",".ToCharArray());
                sb.AppendFormat("{0}('{1}'); ", sqlStatement, splitItems[0]);
            }

        }
        Console.WriteLine(sb.ToString());
        //  conn.Open();
        using (SqlConnection connn = new SqlConnection(ConfigurationManager.ConnectionStrings["whatever"].ConnectionString))

        {
            using (SqlCommand cmd = new SqlCommand(sb.ToString(), connn))
            {
                connn.Open();
                cmd.ExecuteNonQuery();
                connn.Close();
            }
            // Page.ClientScript.RegisterClientScriptBlock(typeof(Page), "Script", "alert('Records Successfuly Saved!');", true);
        }
    }

I tested it as follows:

...
var collection = new StringCollection{"a,x", "b,y", "c,z"};

InsertRecords(collection);

Execution of the database query to see data is as follows:

SELECT [Ingredients1]
  FROM [Ingredients_List]

Results:

Ingredients1
------------
a
b
c
STLDev
  • 5,950
  • 25
  • 36
  • Dump the `StringBuilder`'s content before you execute the query to see exactly what the query is going to be executed. I don't know what you're passing into this function, and am doing my best to help you, but I'm happy to delete my answer if you like. – STLDev Apr 01 '17 at 07:18
  • 1
    var collection = new StringCollection{"a", "b", "c"}; – Steve Apr 01 '17 at 07:56
  • @Steve, yes, I started like that, but you'll see that Tanmay's code contains a `item.Contains(",")` where it is evaluating each member of the collection. If the item doesn't contain a comma, it is not skipped and not inserted into the database. I do not know why it is written like this. – STLDev Apr 01 '17 at 08:00
  • 1
    @STLDeveloper In other words, that is an example of when the OP's code, *and* your modified code, fails with the error the OP is asking about. –  Apr 01 '17 at 08:03
  • what i want is three text boxes in row every time user click and then add that data in the database. If you have any other example then i won't mind using that. – Tanmay Parmar Apr 01 '17 at 17:16
  • @hvd - No, it does not fail as OP's code, nor does it fail at all; and if you had run it you would know that. The OP's posted code is problematic in a few ways - I was trying to show a solution to the original issue he asked about. – STLDev Apr 03 '17 at 15:36
  • Fine. I humoured you. I *literally* copied and pasted your code into a brand new console application (and set up a "whatever" connection string in app.config), I *literally* copied and pasted the argument from Steve's comment. And as expected, I get *exactly* the exception the OP is asking about. That was a frickin' waste of time. –  Apr 03 '17 at 20:23
  • Steve's comment didn't resolve the OP's issue, or if it did, the OP didn't confirm that, so your assumption that his is the proper way to call the method is suspect. Hope you have a great day. – STLDev Apr 03 '17 at 21:07
  • @STLDeveloper *In response to my comment on Steve's comment*, you wrote "it does not fail as OP's code, nor does it fail at all". Whether Steve's comment is appropriate for the OP is no longer relevant -- *you* claimed that your code would work even then. In the context of the comment you were replying to, that claim was flat out untrue. –  Apr 03 '17 at 21:17
  • @hvd - you're right, I did make that assertion, and it's obviously incorrect. I stand corrected. – STLDev Apr 03 '17 at 21:24