Best way to move data between tables in MYSQL - c#

I have a question regarding performance. This is my scenario.
I have a MYSQL database and a application that from time to time moves records, according to the criteria from a query, from one table to another. The way this is done is:
foreach(object obj in list)
{
string id = obj.ToString().Split(',')[0].Trim();
string query = " insert into old_records select * from testes where id='" +
id + "';" + " delete from testes where id='" + id +"'";
DB _db = new DB();
_db.DBConnect(query);
this is the way I connect to the database:
DataTable _dt = new DataTable();
MySqlConnection _conn = new MySqlConnection(connectionString);
MySqlCommand _cmd = new MySqlCommand
{
Connection = _conn,
CommandText = query
};
MySqlDataAdapter _da = new MySqlDataAdapter(_cmd);
MySqlCommandBuilder _cb = new MySqlCommandBuilder(_da);
_dt.Clear();
try
{
_conn.Open();
_cmd.ExecuteNonQuery();
_da.Fill(_dt);
}
catch (MySqlException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (_conn != null) _conn.Close();
}
return _dt;
So my question is, I have like 4000 rows in the table, and it takes a lot of time to move all the records from one table to another, specially across a network. Is there a way to make this faster?
I have been doing some reading and there are several option to handle data from DB like data adapters, reader, set, and tables. Which one is faster for this case? Should I be using a different method?

Two things I see is that first you're opening and closing your connection for each insert, that's usually your most expensive operation so you won't want to do that. You can also try batching them rather than doing them at once. When you do that you have to be careful because things could break in the middle of a large update so you would want to do things in a transaction. Without knowing too much about what your data structure looks like I refactored your method to do batching 100 at a time. First create a little helper method called move items that takes a connection and a list of ids. Don't do a try catch in this, you'll see why later.
Note: This method doesn't use parameters, I highly recommend you change it to do that.
private static void MoveItems(MySqlConnection conn, List<string> moveList)
{
string query = string.Format("insert into old_records select * from testes where id IN({0});" + " delete from testes where id IN({0})", string.Join(",", moveList.ToArray()));
var cmd = new MySqlCommand
{
Connection = conn,
CommandText = query
};
cmd.ExecuteNonQuery();
}
Next you'll change your main method to open the database connection once and then call this method 100 id's at a time. This method will have a try catch therefore if the call to MoveItems throws an exception it will be caught in this main method.
// the using statement will call your dispose method
using (var conn = new MySqlConnection(connectionString))
{
// open the connection and start the transaction
conn.Open();
var transaction = conn.BeginTransaction();
// createa list to temporarily store the ids
List<string> moves = new List<string>();
try
{
// clean the list, do the trim and get everything that's not null or empty
var cleanList = list.Select(obj => obj.ToString().Split(',')[0].Trim()).Where(s => !string.IsNullOrEmpty(s));
// loop over the clean list
foreach (string id in cleanList)
{
// add the id to the move list
moves.Add("'" + id + "'");
// batch 100 at a time
if (moves.Count % 100 == 0)
{
// when I reach 100 execute them and clear the list out
MoveItems(conn, moves);
moves.Clear();
}
}
// The list count might not be n (mod 100) therefore see if there's anything left
if (moves.Count > 0)
{
MoveItems(conn, moves);
moves.Clear();
}
// wohoo! commit the transaction
transaction.Commit();
}
catch (MySqlException ex)
{
// oops! something happened roll back everything
transaction.Rollback();
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
}
You may have to play with that 100 number. I remember when I worked with MySQL a lot I saw some performance differences between doing an IN and giving it a list of Or statements (Id = 'ID1' OR id = 'ID2' ...). But executing 40 statements or 80 statements will certainly have better performance, and opening the database connection once instead of 4000 times should also give you much better performance.

I might be wrong, but there is not much you can do in order to make it faster. After all you want to get the entire table data and insert its information into another table. The process will take some time if your table isn't small. However, you can try using the code below. It should do the trick and save some time.
INSERT INTO TABLE2 (FIELDNAME_IN_TABLE2, FIELDNAME2_IN_TABLE2)
SELECT FIELDNAME_IN_TABLE1, FIELDNAME2_IN_TABLE1
FROM TABLE1

Related

C# - How To Loop Through A Table To Update Each Row MySQL

I'm working on a project where I have to update a table in MySql by looping through it and update every row (one by one) in C#. NOTE: I have to update the value's of only one column in my table.
Now, I know this question has been asked (many times) before but after spending a lot of time searching around the internet I haven't found a solution for my problem.
More Explanation:
So I already know a few things that are necessary to make this work:
I know how to establish a (working) SSH connection.
I know how to establish a (working) MySql connection to my database.
I know how to run/execute a SELECT and UPDATE Query/Command in C#.
So the only thing that I need to make this whole thing work, is the loop itself.
Now, during my research I came across some answers that suggested using a Reader. I don't know if this is what I need and (if yes) how to use it correctly.
Below is the code that I have so far (for establishing the connections and executing query's).
My Code:
class ReaderDemo1
{
public static void Update()
{
Console.WriteLine("[Core] Opening Connection To Database...");
Database.openStockConn(Settings.databaseName, Settings.databaseUsername, Settings.databasePassword, Settings.sshHost, Settings.sshUsername, Settings.sshPassword);
if (Database.stockConn.State != ConnectionState.Open)
{
Database.openStockConn(Settings.databaseName, Settings.databaseUsername, Settings.databasePassword, Settings.sshHost, Settings.sshUsername, Settings.sshPassword);
}
Console.WriteLine("[Core] database connection is now open!\n");
MySqlCommand cmd = new MySqlCommand("SELECT value FROM catalog_product_entity_decimal", Database.stockConn);
try
{
Console.WriteLine("[Price] Updating Prices...");
MySqlCommand command = new MySqlCommand("UPDATE catalog_product_entity_decimal SET value= 1112 WHERE value_id= 4063", Database.stockConn);
command.ExecuteNonQuery();
Console.WriteLine("[Price] Prices Have Been Updated!");
}
catch
{
Console.WriteLine("Updating Failed!");
}
finally
{
if (Database.stockConn != null)
{
Database.stockConn.Close();
}
}
}
}
Just to give some extra context:
Database.cs is where I create the connections (SSH and MySql)
Settings.cs is where I have all the Login data for the SSH and MySql connections.
If you guys would want to know, I have already attempted a few things myself regarding the loop but (as I already mentioned) these attempts weren't successful.
My Attempt With Reader:
using (var reader = command.ExecuteReader())
{
var indexOfValue = reader.GetOrdinal("value");
while (reader.Read())
{
var price1 = reader.GetValue(indexOfValue);
Console.WriteLine("Executing Update Command...");
MySqlCommand cmd = new MySqlCommand("UPDATE catalog_product_entity_decimal SET value= 1222 WHERE entity_id= 759 AND entity_id= 839 AND entity_id= 881", con);
cmd.ExecuteNonQuery();
Console.WriteLine("Update Command Executed!");
}
}
As said, the code above didn't work how I wanted it to work (probably because it isn't actually doing anything now). Just to let you guys know, I am not stuck at an error. I'm just stuck on how to do this.
I hope one of you guys can help me with this or point me in the rigth direction and if you think that my question is a duplicate of another one, just tell me and I will look into it! :) Thanks in advance.
Kind regards,
LKS
EDIT:
In case you guys wanted to know, this is what my table looks like.
The table contains about 5600 rows, so these are just the top rows.
Like Frederiks answer, the thing that you are trying to do now is Looping over an table and execute the same Query over and over again.
Even if you manage to get your code working it would be very slow (because you have about 5600 rows to update).
So my suggestion is that you create an new table with the new value's in it (so the one's you wanted to have after your loop). Then just run a single update command to update your old table with values from your new table.
This option probably takes a few seconds and it will be done, so its much faster! :)
The Query you need should look something like this:
UPDATE old_table
INNER JOIN new_table
USING (column) --> // if you want to update a specific column
EDIT:
In addition/ update to my answer, this is how you can update your table more accurate:
UPDATE old_table
INNER JOIN new_table ON old_table.value_id = new_table.value_id // Use this to set your columns with unique values's
SET old_table.value = new_table.value // For the column with the value's you want to update
So, in the above code you update your old_table with the value's from your new_table. In this example you only update the value's from only one column (which you wanted).
You can expand the query for a different result.
I cannot think of any reason that you would want to read one line at a time and write one line at a time in a loop, but this is how you could do it.
Use one SqlCommand to read and a separate SqlCommand to update. Change the parameters in the loop for each update.
public static void Update()
{
Database.openStockConn(Settings.databaseName, Settings.databaseUsername, Settings.databasePassword, Settings.sshHost, Settings.sshUsername, Settings.sshPassword);
if (Database.stockConn.State != ConnectionState.Open)
{
Database.openStockConn(Settings.databaseName, Settings.databaseUsername, Settings.databasePassword, Settings.sshHost, Settings.sshUsername, Settings.sshPassword);
}
Console.WriteLine("[Core] database connection is now open!\n");
MySqlCommand cmd1 = new MySqlCommand("SELECT value FROM catalog_product_entity_decimal", Database.stockConn);
MySqlCommand cmd2 = new MySqlCommand("UPDATE catalog_product_entity_decimal SET value= 1112 WHERE value_id= 4063", Database.stockConn);
try
{
Console.WriteLine("[Price] Updating Prices...");
using (var reader = cmd1.ExecuteReader())
{
var indexOfValue = reader.GetOrdinal("value");
while (reader.Read())
{
var price1 = reader.GetValue(indexOfValue);
Console.WriteLine("Executing Update Command...");
cmd2.ExecuteNonQuery();
Console.WriteLine("Update Command Executed!");
}
}
}
catch
{
Console.WriteLine("Updating Failed!");
}
finally
{
if (Database.stockConn != null)
{
Database.stockConn.Close();
}
}
}
SQL is set based, which means that there is almost always a better approach then looping over a table.
That is also the case with your problem. You want to avoid looping over an entire table to update record-by-record, since this is terribly slow.
It is not obvious to me on what you're trying to achieve, since your code sample loops over a table and then inside your loop, you execute the same statement over and over again, but you're always updating the exact same records ?
If you want to update records in a table with information coming from another table, you might want to have a look at the UPDATE statement together with the JOIN clause as explained here.
You can try this change , by having the count of rows and then updating the records.
MySqlCommand cmd = new MySqlCommand("SELECT count(*) FROM catalog_product_entity_decimal", Database.stockConn);
try
{
var reader = cmd .ExecuteReader();
if(reader.Read()){
var totalRows=reader.GetInt32(0);
Console.WriteLine("[Price] Updating Prices...");
while(totalRows-->0){
MySqlCommand command = new MySqlCommand("UPDATE catalog_product_entity_decimal SET value= 1112 WHERE value_id= 4063", Database.stockConn);
command.ExecuteNonQuery();
}
Console.WriteLine("[Price] Prices Have Been Updated!");
}
}
catch
{
Console.WriteLine("Updating Failed!");
}
finally
{
if (Database.stockConn != null)
{
Database.stockConn.Close();
}
}

Updating a DB (SQL Server) using Ids from a dataTable in C# without For loop

its my first question on S.O, also I'm kinda new in c# and SqlServer.
so pretty please be nice.
I have a dataTable with 4 columns: id1, id2, id3, id4 (and several rows)
also I have a SQL Server DB containing the 4 columns and additional columns, 2 of them named field1 and field2
I want to Update field1 and field2 to null in the db (without using foreach Row)
I've succeeded updating the first row using this:
public void UpdateDt(DataTable dt, string ConnectionString)
{
Conn = null;
DataRow row = dt.Rows[0]
try
{
Conn = new SqlConnection(ConnectionString);
Conn.Open();
string sql = "update [DB].[dbo].[MyTable] set [field1] = null,"+
"[field2] = null where [ID1] = '"+row["ID1"]+"' and [ID2] = '"+row["ID2"]+"' "+
"and [ID3] = '"+row["ID3"]+"' and [ID4] = '"+row["ID4"]+"'";
var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
sqlDataAdapter.UpdateCommand.CommandText = sql;
sqlDataAdapter.UpdateCommand.BeginExecuteNonQuery();
}
catch( Exception ex) log(ex);
finally
{
if (Conn != null)
{
Conn.Close();
Conn.Dispose();
}
}
}
how can I update using the entire DataTable?
please help
thanks in advance
-- response to comment by Soner Gönül
I've changed the sample code according to your advice, thanks
Zohar,thanks, I've chosen the fields names in order to try and make the question more general and understandable
---edit---
I've added a code for updating the entire DataTable using ForEach (with the help of Russ (thanks Russ))
bool UpdateDt(DataTable dt)
{
Conn = null;
try
{
Conn = new SqlConnection(ConnectionString);
Conn.Open();
string sql = "update [KeywordInjectionData] " +
"set " +
"[field1] = null " +
",[field2] = null " +
"where " +
"[Id1] = #Id1" +
" and [Id2] = #Id2" +
" and [Id3] = #Id3" +
" and [Id4] = #Id4;" ;
var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
foreach (DataRow row in dt.Rows)
{
sqlDataAdapter.UpdateCommand.CommandText = sql;
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("#Id1",row["Id1"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("#Id2",row["Id2"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("#Id3",row["Id3"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("#Id4",row["Id4"]);
sqlDataAdapter.UpdateCommand.ExecuteNonQuery();
sqlDataAdapter.UpdateCommand.Parameters.Clear();
}
}
catch (Exception e1)
{
Utillties.LogError(e1);
return false;
}
finally
{
if (Conn != null)
{
Conn.Close();
Conn.Dispose();
}
}
return true;
}
but the question remains, how can I update the DB without a ForEach loop?
First off, the way you are structuring your query is extremely dangerous as it will allow SQL Injections--you should only use parameterized queries (as mentioned by Soner Gonul in the comments above).
Second you can loop through each row with a Foreach clause:
Foreach (DataRow row in dt.Rows)
In doing this, however, you should move the connection declaration and open before the Foreach so that you only open the connection once.
I'm not sure why you wouldn't want to use a loop in this instance. In general, at a pure database level, loops are considered "bad", but that's really an over simplification of the issue... (I've written many queries that are faster with a loop than without)
Let's start by removing C# from the question, and instead make it "how to update all desired rows in a table at once?" Since the new values are all the same, it's possible, provided you can create the appropriate where clause. In this case, since you're attempting to update a random set of rows based on (I assume) user input, it would need to look like the following:
UPDATE dbo.MyTable
SET field1 = null, field2 = null
WHERE (id1 = #m1_id1 AND id2 = #m1_id2 AND id3 = #m1_id3)
OR (id1 = #m2_id1 AND id2 = #m2_id2 AND id3 = #m2_id3)
OR (id1 = #m3_id1 AND id2 = #m3_id2 AND id3 = #m3_id3)
etc.
Which get's silly rather quick. For the sake of completeness, if instead you were referencing another table in the database, it would be possible to do the following (under most RDBMS's):
UPDATE myT
SET field1 = null, field2 = null
FROM dbo.MyTable myT
JOIN dbo.SetsToUpdate s ON myT.id1=s.id1
AND myT.id2=s.id2
AND myT.id3=s.id3
However, you're not starting with another table, and setting one up, populating it and cleaning it up most likely requires more resources than simply multiple single row updates.
So, we're back at a loop, but one that's performed in C# which does loops quite effectively. Further, aside from performance, the only other reason to want a single update statement is data atomicity, which is handled quite nicely with transactions.
If you really do see performance issues at the database level here, the question is one of database optimization (look into indexes). But please, don't fall into the trap of premature optimization.

Insert data into Sql Compact

I have Handheld device that connect to Sql Server database, read the Sql server data and get it on the SQL Compact database that is located on device. This is my code:
public void InsertData() // Function insert data into SQL commapct database
{
dt = new DataTable();
dt = SqlServer_GetData_dt("Select id_price, price, id_item from prices", SqlCeConnection); // get data form sql server
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
string sql = "";
sql = "insert into prices" +
" ( id_prices, price,id_item) values('"
+ dt.Rows[i]["id_price"].ToString().Trim() + "', '"
+ dt.Rows[i]["price"].ToString().Trim() + "', '"
+ dt.Rows[i]["id_item"].ToString().Trim() + "')";
obj.SqlCE_WriteData_bit(sql, connection.ConnectionString);//insert into sql compact
}
}
}
public DataTable SqlServer_GetData_dt(string query, string conn)
{
try
{
DataTable dt = new DataTable();
string SqlCeConnection = conn;
SqlConnection sqlConnection = new SqlConnection(SqlCeConnection);
sqlConnection.Open();
{
SqlDataReader darSQLServer;
SqlCommand cmdCESQLServer = new SqlCommand();
cmdCESQLServer.Connection = sqlConnection;
cmdCESQLServer.CommandType = CommandType.Text;
cmdCESQLServer.CommandText = query;
darSQLServer = cmdCESQLServer.ExecuteReader();
dt.Load(darSQLServer);
sqlConnection.Close();
}
return dt;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
DataTable dt = new DataTable();
return dt;
}
}
public object SqlCE_WriteData_bit(string query, string conn)
{
try
{
string SqlCeConnection = conn;
SqlCeConnection sqlConnection = new SqlCeConnection(SqlCeConnection);
if (sqlConnection.State == ConnectionState.Closed)
{
sqlConnection.Open();
}
SqlCeCommand cmdCESQLServer = new SqlCeCommand();
cmdCESQLServer.Connection = sqlConnection;
cmdCESQLServer.CommandType = CommandType.Text;
cmdCESQLServer.CommandText = query;
object i = cmdCESQLServer.ExecuteScalar();
sqlConnection.Close();
return i;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return 0;
}
}
This is all work fine but the problem is that all this work very slow. I have 20 000 row that's need to be inserted into SQL compact database.
Is there any way for faster insert?
Thanks.
Aside from the obvious poor usage of the Connection for every call, you can greatly improve things by also eliminating the query processor altogether. That means don't use SQL. Instead open the destination table with TableDirect and a SqlCeResultset. The iterate through the source data (a DataTable is a bad idea, but that's a completely different thing) and use a series of CreateRecord, SetValues and Insert.
A pretty good example can be found here (though again, I'd use SetValues to set the entire row, not each individual field).
Reuse your connection and don't create a new connection for every INSERT statement.
Instead of passing a connection string to your SqlCE_WriteData_bit method, create the connection once in the InsertData method, and pass the connection object to SqlCE_WriteData_bit.
Put all the data into a DataTable and then use a SqlCeDataAdapter to save all the data with one call to Update. You may have to fiddle with the UpdateBatchSize to get the best performance.
Looking more closely, I see that you already have a DataTable. Looping through it yourself is therefore ludicrous. Just note that, as you have it, the RowState of every DataRow will be Unchanged, so they will not be inserted. I think that you can call DataTable.Load such that all RowState values are left as Added but, if not, then use a SqlDataAdapter instead, set AcceptChangesDuringFill to false and call Fill.
Is there any way for faster insert?
Yes, but it probably won't be "acceptably fast enough" when we're talking about inserting 20k rows.
The problem I can see is that you are opening a connection for every single row you are retrieving from SqlServer_GetData_dt, that is, you open a connection to insert data 20k times...opening a connection is an expensive transaction. You should build the whole query using a StringBuilder object and then execute all the insert statements in one batch.
This will bring some performance gains but don't expect it to solve you're problem, inserting 20k rows will still take some time, specially if indexes need to be re-built. My suggestion is that you should thoroughly analyse your requirements and be a bit smarter about how you approach it. Options are:
bundle a pre-populated database if possible so your app doesn't have to suffer the population process performance penalties
if not, run the insert process in the background and access the data only when the pre-population is finished

data reader in ado.net

I have a data reader object, which reads through say 4 rows, and I will be looping through the rows. While reading third row, I insert a row inside the same table, will my data reader be able to read the newly inserted row. If not how to achieve this functionality
Here is the code i tried.
AseCommand sessionCmd = null;
//AseCommand selectCmd = null;
AseCommand insertCmd = null;
AseDataReader reader = null;
string retCode = "Nothing returned from the Server";
string insertStatement;
AseConnection conn = null;
conn = new AseConnection("Data Source='" + host + "';Port='" + port + "';UID='" + user + "';PWD='" + password + "';Database=" + db + ";");
conn.Open();
sessionCmd = new AseCommand("select * from dbo.DummyTable", conn);
try
{
reader = sessionCmd.ExecuteReader();
int count = 0;
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
count++;
if (count == 3)
{
//insert into table
insertCmd = new AseCommand("insert into DummyTable values (5)", conn);
insertCmd.ExecuteReader();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
I found your question interesting, because I thought the context would along the lines if a row being added from another process, would the current reader see it.
If I had written your test and it did not produce the result I expected, I might come to Stackoverflow and ask: is it possible to read the new row and I just did not do it right? or maybe even get an answer like: it might work sometimes but not always because of xyz...
However, you got answer three, which was 'don't bother us, we didn't sleep well last night.'
In general terms, a DataReader is a read-only forward-reading stream of tabular data sets. It is streaming the results of a query, not monitoring a table...so the query results have already been executed by the database and are being served when called,but not being updated.
Incidentally, what you did was insert a new row using an ExecuteReader command, which returned a new reader...it doesn't modify the outer reader you are looping through. You could read the results of the insert from the new reader...although its not quite clear why you would want to.
Although probably beyond the scope of your test, you might be interested in the concept of Multiple Active Result Sets which does allow you to go back and forth between two results sets on the same connection.

Read records from one table , and write to another table. Exception occurs procedure or function has too many arguments specified?

I am trying to retrieve list of records from one table , and write to another table. I've used a simple query to retrieve the values to SqlDataReader,then load them to a DataTable. Using the DataTableReader , I am going through the entire data set which is Saved in DataTable. The problem is, while reading each and every record I am trying to insert those values to another table using a Stored Procedure.But it only insert the first row of values,and for the second row onward giving some Exception saying."procedure or function has too many arguments specified".
string ConStr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
SqlConnection NewCon = new SqlConnection(ConStr);
NewCon.Open();
SqlCommand NewCmd3 = NewCon.CreateCommand();
NewCmd3.CommandType = CommandType.Text;
NewCmd3.CommandText ="select * from dbo.Request_List where group_no ='" +group_no+ "'";
NewCon.Close();
NewCon.Open();
SqlDataReader dr = (SqlDataReader)NewCmd3.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
DataTableReader reader = new DataTableReader(dt);
NewCmd.Dispose();
NewCon.Close();
NewCon.Open();
SqlCommand NewCmdGrpReqSer = NewCon.CreateCommand();
NewCmdGrpReqSer.CommandType = CommandType.StoredProcedure;
NewCmdGrpReqSer.CommandText = "Voucher_Request_Connection";
if (reader.HasRows)
{
int request_no = 0;
while (reader.Read())
{
request_no = (int)reader["request_no"];
NewCmdGrpReqSer.Parameters.Add("#serial_no", serial_no);
NewCmdGrpReqSer.Parameters.Add("#request_no", request_no);
try
{
NewCmdGrpReqSer.ExecuteNonQuery();
MessageBox.Show("Connection Updated");//just to check the status.tempory
}
catch (Exception xcep)
{
MessageBox.Show(xcep.Message);
}
MessageBox.Show(request_no.ToString());//
}
NewCmdGrpReqSer.Dispose();
NewCon.Close();
}
Any Solutions ?
As #Sparky suggests, the problem is that you continue to add parameters to the insertion command. There are several other ways in which the code could be improved, however. These improvements would remove the need to clear the parameters and would help to make sure you don't leave disposable resources undisposed.
First - use the using statement for your disposable objects. This removes the need for the explicit Close (btw, only one of Close/Dispose is needed for the connection as I believe Dispose calls Close). Second, simply create a new command for each insertion. This will prevent complex logic around resetting the parameters and, possibly, handling error states for the command. Third, check the results of the insertion to make sure it succeeds. Fourth, explicitly catch a SqlException - you don't want to accidentally hide unexpected errors in your code. If it's necessary to make sure all exceptions don't bubble up, consider using multiple exception handlers and "doing the right thing" for each case - say logging with different error levels or categories, aborting the entire operation rather than just this insert, etc. Lastly, I would use better variable names. In particular, avoid appending numeric identifiers to generic variable names. This makes the code harder to understand, both for others and for yourself after you've let the code sit for awhile.
Here's my version. Note there are several other things that I might do such as make the string literals into appropriately named constants. Introduce a strongly-typed wrapper around the ConfigurationManager object to make testing easier. Remove the underscores from the variable names and use camelCase instead. Though those are more stylistic in nature, you might want to consider them as well.
var connectionString = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
using (var newConnection = new SqlConnection(connectionString))
{
newConnection.Open();
using (var selectCommand = newConnection.CreateCommand())
{
selectCommand.CommandType = CommandType.Text;
select.CommandText ="select request_no from dbo.Request_List where group_no = #groupNumber";
selectCommand.Parameters.AddWithValue("groupNumber", group_no);
using (dataReader = (SqlDataReader)newCommand.ExecuteReader())
{
while (reader.HasRows && reader.Read())
{
using (var insertCommand = newConnection.CreateCommand())
{
insertCommand.CommandType = CommandType.StoredProcedure;
insertCommand.CommandText = "Voucher_Request_Connection";
var request_no = (int)reader["request_no"];
insertCommand.Parameters.Add("#serial_no", serial_no);
insertCommand.Parameters.Add("#request_no", request_no);
try
{
if (insertCommand.ExecuteNonQuery() == 1)
{
MessageBox.Show("Connection Updated");//just to check the status.tempory
}
else
{
MessageBox.Show("Connection was not updated " + request_no);
}
}
catch (SqlException xcep)
{
MessageBox.Show(xcep.Message);
}
MessageBox.Show(request_no.ToString());//
}
}
}
}
}
Try clearing your parameters each time...
while (reader.Read())
{
request_no = (int)reader["request_no"];
// Add this line
NewCmdGrpReqSer.Parameters.Clear();
NewCmdGrpReqSer.Parameters.Add("#serial_no", serial_no);
NewCmdGrpReqSer.Parameters.Add("#request_no", request_no);
try
{

Categories

Resources