0

I am developing a front-end sales application.

Is this an efficient way of inserting data multiple times into a sql table, from a single button:

private void button1_Click(object sender, EventArgs e)
{
    c.Open();
    string w = "insert into checkmultiuser(username) values (@username)";

    SqlCommand cmd = new SqlCommand(w, c);

    cmd.Parameters.Add("@username", SqlDbType.VarChar);
    cmd.Parameters["@username"].Value = textBox1.Text;
    //cmd.ExecuteNonQuery();
    cmd.ExecuteReader();
    c.Close();    
}

What are its drawbacks? One would be that again and again the connection is opened and closed when the button is clicked which would effect the speed greatly.

Dan Puzey
  • 33,626
  • 4
  • 73
  • 96
sqlchild
  • 8,754
  • 28
  • 105
  • 167

5 Answers5

2

You ar edoing the right way: see this question: to close connection to database after i use or not? too.

Community
  • 1
  • 1
Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
2

Perhaps don't do the database insert for each entry, but store each entry in a DataSet, then insert them all at once, a la a save button.

For each entry do this:

String s = textBox1.Text;

If ( *\Enter validation logic*\ )
{
  //Insert data into DataSet
}
else
{
  //Throw error for user.
}

Then once you're ready to commit to DB, insert each item from the DataSet, similar to the examples in the other answers here.

MAW74656
  • 3,449
  • 21
  • 71
  • 118
  • can conditions or validations be applied on Datasets? – sqlchild Apr 04 '11 at 06:58
  • I don't know about that, but why bother waiting to do them then? Can you do the validations without hitting the database? If so, they validate each entry as its entered into the DataSet. If you do need data from database, perhaps you could retrieve the data once at the beginning, store that into a separate dataset, then compare entries to that data. Less round trips to the db server. – MAW74656 Apr 04 '11 at 14:07
  • @MAW74656- sir, so can i filter data which is entered into the database , first in the dataset and then send that filtered data in the database – sqlchild Apr 04 '11 at 15:27
  • Depends what you mean by "filter". If you want to copy a part of a dataset to the database, thats no problem. Just use the DataSet.Select() method to grab the entries you need. – MAW74656 Apr 04 '11 at 15:33
  • By filter i meant that can i put validations on the dataset? – sqlchild Apr 07 '11 at 05:13
  • Probably the best way is to validate each record BEFORE you put it into the dataset. 1) Grab data from the textboxes 2) check that data for conditions you specify 3) If the data passes, insert into dataset, otherwise, put up an error message for the user. – MAW74656 Apr 07 '11 at 19:24
  • See my edit. Also, use SqlCommand.Parameters.AddWithValue(string parametername, object value) which will cut your 2 lines of parameter code down to 1. Not that big a deal in this instance, but if you have 9 parameters, it can get messy. – MAW74656 Apr 07 '11 at 19:31
  • @MAW74656 : sir, can i insert data into a dataset? if yes, then can i put that insert query into a transaction? – sqlchild Apr 09 '11 at 11:24
  • @MAW74656 : if yes, then can i put that insert query into a transaction? as i want a mediator between my actual database and the user , so i think dataset would act as a mediator? is it so? – sqlchild Apr 09 '11 at 12:03
0

I would open the connection once when the form opens and re-use that connection until the form is closed.

As for inserting records, the code you have is right.

Druid
  • 6,423
  • 4
  • 41
  • 56
0

From a resource management point of view it would be better if you can work out how many times you need to insert the data and then perform the operation in the one button click, perhaps iterating through a loop until the correct amount of insert operations has been completed. This means you are not constantly opening and closing the connection with each button press but instead opening it, performing the insert queries and closing the connection.

Also I recommend that you implement your code with the "using" statement, this way it will automatically handle the disposal and release of resources.

private void button1_Click(object sender, EventArgs e, string[] value)
{
      try
      {
           using(SQLConnection c = new SQLConnection(connectionString))  
           using(SQLCommand cmd = new SQLCommand(c))
           {
               c.Open();

               string w = "insert into checkmultiuser(username) values (@username)";

               cmd.CommandText = w;
               cmd.Parameters.Add("@username", SqlDbType.VarChar);    

               for(int i = 0; i < value.Length; i++)
               {
                   cmd.Parameters["@username"].Value = value[i];    
                   cmd.ExecuteReader();
               }
           }
        }
        catch(Exception e)
        {
             Console.WriteLine(e.Message);
        }
}

If you can create the SQLConnection in the method then it will also allow you create it in a using statement, again taking care of managing and releasing resources.

In terms of the statement you are using I can't see any problems with it, you're using parameterized queries which is a good step to take when interacting with SQL databases.

References:

try-catch - MSDN

Jamie Keeling
  • 9,806
  • 17
  • 65
  • 102
  • Your code will not compile: `c` is out of scope when you call `c.Close()` – Dan Puzey Mar 31 '11 at 13:06
  • The changes should be reflected, had to fight with the editor. – Jamie Keeling Mar 31 '11 at 13:11
  • @Jamie Keeling : sir, as it would be a front-end sales application, so its obvious that names of product sold would be input into the database and a bill would be generated for the customers very frequently, as it would be for a large scale firm. in this case, what do you suggest? – sqlchild Mar 31 '11 at 14:03
  • Would each product be process per transaction as your original code suggests or will you be wanting to process multiple products on one transaction? – Jamie Keeling Mar 31 '11 at 14:21
  • 1
    In code provided above, why are you closing the connection explicitly? Since you are using a "using" statement it will dispose and close the connection for you. – Hadi Eskandari Mar 31 '11 at 16:34
  • @Jamie Keeling: sir, i would process single product insert per transaction. in this way every product would either go or not in the database because i want to be safe from power cut issues. – sqlchild Apr 04 '11 at 07:01
  • It might be easier if you group all of the insertions into one transaction, it would mean you're not opening and closing the connection as often. If there is a power cut during the insertion of the third product for example then there would be no changes to the database itself due to the transaction not completing and committing, progress can be rolled back to it's previous state so you can try again when power is restored. It really does depend how comfortable you are with it in general – Jamie Keeling Apr 04 '11 at 09:54
0

I don't think you should have to worry about the time lag due to opening and closing a connection, particularly if it is happening on a manually triggered button click event. Human perceivable response time is about 200 milliseconds. At best, I'd guess someone could click that button once every 100 milliseconds or so. Plenty of time to open and close a connection.

If, however, you are dealing with a routine that will be connecting to your database, you could pass in the connection, include a using statement as Mr. Keeling mentioned already, and just verify that it is ready.

Here is yet another approach, which returns a DataTable (since your original post displayed executing a Data Reader):

public static DataTable UpdateRoutine(SQLConnection c, string value) {
  const string w = "insert into checkmultiuser(username) values (@username)";
  DataTable table = new DataTable();
  using(SQLCommand cmd = new SQLCommand(w, c)) {
    cmd.Parameters.Add("@username", SqlDbType.VarChar);
    cmd.Parameters["@username"].Value = value;
    try {
      if ((cmd.Connection.State & ConnectionState.Open) != ConnectionState.Open) {
        cmd.Connection.Open();
      }
      using (SqlDataReader r = cmd.ExecuteReader()) {
        table.Load(r);
      }
    }
    return table;
  } catch(SqlException err) { // I try to avoid catching a general exception.
    MessageBox.Show(err.Message, "SQL Error");
  }
  return null;
}