Issue with Open DataReader which must be closed first - c#

I am getting the following error in my code:
"There is already an open DataReader associated with this Command
which must be closed first."
I have two SqlDataReaders and I made sure that I closed the first one after loading the DataViewGrid.
Below is the function that is giving me the issue. I marked the line that is throwing the error. I've tried variations with 'try' and 'using', I've tried to rename diff SqlConnections, SqlDataReaders and SqlCommands. I am at a loss here.
Can I not have an open SqlDataReader and SqlCommand open at the same time on one connection?
private void ApprovedTransferAction(int rowNum) {
bool foundFlag = false;
//int XferQty = (int)gridData.Rows[rowNum].Cells["FinalQty"].Value;
string PorgID = "";
using (SqlConnection conn = new SqlConnection(Global.connString)) {
conn.Open();
// Locate id in PorgReqs
string sqlSelectQuery = "SELECT id FROM PorgReqs WHERE location_id = #NewLocationID AND vendor_id = #VendorID AND item_id = #Item";
using (SqlCommand sqlSelect = new SqlCommand(sqlSelectQuery, conn)) {
sqlSelect.Parameters.Add("#NewLocationID", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["NewLocation"].Value;
sqlSelect.Parameters.Add("#VendorID", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["Vendor"].Value;
sqlSelect.Parameters.Add("#Item", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["Item"].Value;
using (SqlDataReader sqlDataReader2 = sqlSelect.ExecuteReader()) {
// If Item is found at Target Location; FinalQty of Source Added to AddlQty of Target
if (sqlDataReader2.HasRows) {
sqlDataReader2.Read();
PorgID = Convert.ToString(sqlDataReader2["id"]);
MessageBox.Show("Found ID: " + PorgID);
string sqlUpdateQuery = "UPDATE PorgReqs SET AddlQty += #XferQty WHERE id = #ID";
using (SqlCommand sqlUpdate = new SqlCommand(sqlUpdateQuery, conn)) {
sqlUpdate.Parameters.Add("#XferQty", SqlDbType.Int).Value = (int)gridData.Rows[rowNum].Cells["FinalQty"].Value;
sqlUpdate.Parameters.Add("#ID", SqlDbType.Int).Value = sqlDataReader2["id"];
sqlUpdate.CommandType = CommandType.Text;
sqlUpdate.ExecuteNonQuery();
} // End sqlUpdate Command
} else { // Item was not found at Target location
string sqlUpdateQuery = "UPDATE PorgReqs SET " +
" location_id = #TargetLoc, " +
" requirement_location_id = #TargetLoc, " +
" ship_to_location_id = #TargetLoc " +
" WHERE " +
" location_id = #SourceLoc AND " +
" vendor_id = #VendorID AND " +
" item_id = #Item";
using (SqlCommand sqlUpdate = new SqlCommand(sqlUpdateQuery, conn)) {
sqlUpdate.Parameters.Add("#TargetLoc", SqlDbType.Int).Value = gridData.Rows[rowNum].Cells["NewLocation"].Value;
sqlUpdate.Parameters.Add("#SourceLoc", SqlDbType.Int).Value = gridData.Rows[rowNum].Cells["Location"].Value;
sqlUpdate.Parameters.Add("#VendorID", SqlDbType.Int).Value = gridData.Rows[rowNum].Cells["Vendor"].Value;
sqlUpdate.Parameters.Add("#Item", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["Item"].Value;
sqlUpdate.CommandType = CommandType.Text;
sqlUpdate.ExecuteNonQuery(); // ERROR HERE
} // End sqlUpdate Command
} // End Else
sqlDataReader2.Close();
}
/*} catch (Exception ex) {
Console.WriteLine(ex.Message);
MessageBox.Show("Try SQLReader: " + ex.Message);
} */
} // End sqlSelect Command
} // End SQL Connection
// See if id exists in grid
MessageBox.Show("Checking Grid");
foreach (DataGridViewRow row in gridData.Rows) {
if (foundFlag == true)
break;
else if (row.Cells["id"].Value.ToString() == PorgID) {
// Update grid
row.Cells["AddlQty"].Value = Convert.ToInt32(gridData.Rows[rowNum].Cells["FinalQty"].Value) + Convert.ToInt32(row.Cells["AddlQty"].Value);
row.Cells["FinalQty"].Value = Convert.ToInt32(row.Cells["RecQty"].Value) + Convert.ToInt32(row.Cells["AddlQty"].Value);
foundFlag = true;
MessageBox.Show("Found: " + foundFlag);
} // End If
} // End ForEach
// Remove the Row from the Grid
gridData.Rows.RemoveAt(rowNum);
}

Just add MultipleActiveResultSets=true to your connection string.

Related

How would you go about debugging Specified Cast is not valid, using dates?

https://ibb.co/DkKdpnL
This is the code im using in the Database controller. Im sure there is nothing wrong with this code but i keep on getting the error message when I select a date from the Monthly calender Picker.
{
SqlDataReader reader;
SqlCommand command;
Collection<StockItem> items;
try
{
DateTime input;
DateTime.TryParse(date, out input);
command = new SqlCommand("SELECT * FROM StockItem WHERE DATEDIFF(day, stockItemExpiryDate,'" + input.ToString() + "') >= 0 ORDER BY stockItemShelfNumber", cnMain);
cnMain.Open();
command.CommandType = CommandType.Text;
reader = command.ExecuteReader();
items = new Collection<StockItem>();
if (reader.HasRows)
{
while (reader.Read())
{
StockItem item = new StockItem();
item.expiryDate = reader.GetDateTime(1).ToShortDateString();
item.shelfNumber = reader.GetString(2);
item.numberInStock = reader.GetInt32(3) + "";
item.productRef = reader.GetInt32(4) + "";
SqlConnection connection = newConn();
SqlCommand command2 = new SqlCommand("SELECT productPackaging FROM Product WHERE productID =" + item.productRef + ";", connection);
connection.Open();
command2.CommandType = CommandType.Text;
SqlDataReader reader2 = command2.ExecuteReader();
String description = "";
if (reader2.HasRows)
{
reader2.Read();
description = reader2.GetString(0);
}
reader2.Close();
connection.Close();
item.productRef = description;
items.Add(item);
}
}
reader.Close();
cnMain.Close();
this.items = items;
return items;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
cnMain.Close();
Console.WriteLine(ex.ToString());
}
return null;
}```
From the error, I assume the exception is being raised by
item.expiryDate = reader.GetDateTime(1).ToShortDateString();
Logically, field 1 (The second column) in your StockItem table isn't a Date/Time. I'd check your table, and if you're sure that's right, maybe use reader.GetValue(1) instead, and see what you get.

c# Connection must be valid and open to commit transaction TransactionScope

I'm using Transactions on my Dao and in particular I'm using the TransactionScope object for the first time. But when I compile and start my procedure on my pc the method I wrote in will give me this error:
Connection must be valid and open to commit transaction
code:
public String insert(NewsVo news)
{
string query = "";
MySqlCommand cmd = null;
try
{
using (TransactionScope scope = new TransactionScope())
{
using (MySqlConnection conn = new MySqlConnection("Server=localhost;Uid=root;Pwd=root;Database=Sql300365_1"))
{
conn.Open();
Int32 numTotali = Int32.Parse(getCount());
for (int i = numTotali - 1; i >= 0; i--)
{
query = "UPDATE " + table + " SET " + table + ".Priorita = ?PrioritaSet WHERE Priorita = ?Priorita";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.Add("?Priorita", MySqlDbType.Int64).Value = i;
cmd.Parameters.Add("?PrioritaSet", MySqlDbType.Int64).Value = i + 1;
cmd.ExecuteReader();
}
query = "INSERT INTO " + table + " (Priorita, Data, Titolo) VALUES (0, ?Data, ?Titolo)";
cmd = new MySqlCommand(query, conn);
//cmd.Transaction = Transazione;
cmd.Parameters.Add("?Data", MySqlDbType.VarChar, ConstDao.LENGHT_NEWS_DATA).Value = news.Data;
cmd.Parameters.Add("?Titolo", MySqlDbType.VarChar, ConstDao.LENGHT_NEWS_TITOLO).Value = news.Titolo;
cmd.ExecuteReader();
news.IdNumber = cmd.LastInsertedId.ToString();
scope.Complete();
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
finally
{
cmd.Dispose();
}
return news.IdNumber;
}
You need to move scope.Complete(); within your connection using as it is being disposed before you are completing your scope. Also, change your calls to use ExecuteNonQuery as opposed to ExecuteReader, as you are opening a SqlDataReader and not disposing of it.
using (MySqlConnection conn = new MySqlConnection("Server=localhost;Uid=root;Pwd=root;Database=Sql300365_1"))
{
conn.Open();
Int32 numTotali = Int32.Parse(getCount());
for (int i = numTotali - 1; i >= 0; i--)
{
query = "UPDATE " + table + " SET " + table + ".Priorita = ?PrioritaSet WHERE Priorita = ?Priorita";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.Add("?Priorita", MySqlDbType.Int64).Value = i;
cmd.Parameters.Add("?PrioritaSet", MySqlDbType.Int64).Value = i + 1;
cmd.ExecuteNonQuery();
}
query = "INSERT INTO " + table + " (Priorita, Data, Titolo) VALUES (0, ?Data, ?Titolo)";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.Add("?Data", MySqlDbType.VarChar, ConstDao.LENGHT_NEWS_DATA).Value = news.Data;
cmd.Parameters.Add("?Titolo", MySqlDbType.VarChar, ConstDao.LENGHT_NEWS_TITOLO).Value = news.Titolo;
cmd.ExecuteNonQuery();
news.IdNumber = cmd.LastInsertedId.ToString();
scope.Complete();
}
ok Ok i have inverted using connection with scope
And I opened the connection before scope and works !
I hope it is right, thank you !
public String insert(NewsVo news)
{
string query = "";
MySqlCommand cmd = null;
try
{
using (MySqlConnection conn = new MySqlConnection("Server=localhost;Uid=root;Pwd=root;Database=Sql300365_1"))
{
using (TransactionScope scope = new TransactionScope())
{
conn.Open();
Int32 numTotali = Int32.Parse(getCount());
for (int i = numTotali - 1; i >= 0; i--)
{
query = "UPDATE " + table + " SET " + table + ".Priorita = ?PrioritaSet WHERE Priorita = ?Priorita";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.Add("?Priorita", MySqlDbType.Int64).Value = i;
cmd.Parameters.Add("?PrioritaSet", MySqlDbType.Int64).Value = i + 1;
cmd.ExecuteNonQuery();
}
query = "INSERT INTO " + table + " (Priorita, Data, Titolo) VALUES (0, ?Data, ?Titolo)";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.Add("?Data", MySqlDbType.VarChar, ConstDao.LENGHT_NEWS_DATA).Value = news.Data;
cmd.Parameters.Add("?Titolo", MySqlDbType.VarChar, ConstDao.LENGHT_NEWS_TITOLO).Value = news.Titolo;
cmd.ExecuteNonQuery();
news.IdNumber = cmd.LastInsertedId.ToString();
scope.Complete();
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
finally
{
cmd.Dispose();
}
return news.IdNumber;
}

Error in gridviewUpdating asp.net with a timestamp update

I have two buttons, SetIn and SetOut. They both have the commandName UPDATE ( I have two buttons as I'd like the text to be different on the button depending on the value of one field in the row.
I'm getting a problem in that when I run the update SQL statement, it throws an error at me. It says:
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
Additional information: Incorrect syntax near '14'.
This means that there is an issue with the date and time stamp that I am trying to update the row with (I'm making the update at 14.02pm).
My aspx.cs page code is:
protected void GridView1_RowUpdating(object sender, System.Web.UI.WebControls.GridViewUpdateEventArgs e)
{
Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
int rowToUpdate = Int32.Parse(id.Text);
con = new SqlConnection(cs);
int scopeValue;
con = new SqlConnection(cs);
cmd = new SqlCommand();
cmd.CommandText = "SELECT in_scope FROM " + databaseName + " WHERE id = '" + rowToUpdate + "'";
cmd.Parameters.AddWithValue("#id", rowToUpdate);
cmd.Connection = con;
try
{
con.Open();
scopeValue = Convert.ToInt32(cmd.ExecuteScalar());
//database_entries.Text = recordCount.ToString();
}
finally
{
con.Close();
}
string modifiedBy = userManagement.getWeldID();
string updateDate = DateTime.UtcNow.ToString("dd/MMM/yyyy HH:mm:ss");
{
if (scopeValue == 1)
{
// Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
string sqlStatement = "";
con = new SqlConnection(cs);
// SqlCommand cmd = new SqlCommand();
sqlStatement = #"update dbo.Fair_Use_InScope_MIF_Alex_temp set in_scope = '0', modified_by = " + modifiedBy + ", date_updated = " + updateDate + " where id = '" + rowToUpdate + "'";
con.Open();
cmd = new SqlCommand(sqlStatement, con);
cmd.ExecuteNonQuery();
con.Close();
ShowData();
}
if (scopeValue == 0)
{
// Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
string sqlStatement = "";
con = new SqlConnection(cs);
// SqlCommand cmd = new SqlCommand();
sqlStatement = #"update dbo.Fair_Use_InScope_MIF_Alex_temp set in_scope = '1', modified_by = " + modifiedBy + ", date_updated = " + updateDate + " where id = '" + rowToUpdate + "'";
con.Open();
cmd = new SqlCommand(sqlStatement, con);
cmd.ExecuteNonQuery();
con.Close();
ShowData();
}
}
}
I'm basically trying to get the scopeValue (0 or 1) of the row, and if the Update command is called, and the scopeValue was previously 0, set it to 1 now and vice versa. I also need to update the time that the change was made and who made the change in that row. (these are both displayed in the gridview)
Any help would be much appreciated as I am a beginner to ASP.NET and C# and SQL SERVER!!
You are sending a DateTime as a string (without even enclosing single quotes date_updated = '" + updateDate + "') and that will always cause problems.
It's better to use parameters in your query. This prevents SQL injection, improves readability, ensures type safety, no more worries about the correct use of quotation marks etc.
string sqlStatement = "UPDATE dbo.Fair_Use_InScope_MIF_Alex_temp SET in_scope = 0, modified_by = #modifiedBy, date_updated = #updateDate WHERE (id = #rowToUpdate)";
using (SqlConnection connection = new SqlConnection(cs))
using (SqlCommand command = new SqlCommand(sqlStatement, connection))
{
command.Parameters.Add("#modifiedBy", SqlDbType.VarChar).Value = modifiedBy;
command.Parameters.Add("#updateDate", SqlDbType.DateTime).Value = DateTime.Now;
command.Parameters.Add("#rowToUpdate", SqlDbType.Int).Value = 35;
connection.Open();
command.ExecuteNonQuery();
}

Nothing happens on query execution

I have this simple code C# and SQL Server database:
int refcodenum = getOrderNum();
string refcode = "E" + refcodenum;
byte[] personalpic = getBarcode(refcodenum);
SqlCommand cm2 = new SqlCommand();
cm2.Connection = cn;
cm2.CommandText = "Update Clients set ReferenceNumber='" + refcode + "',ReferenceBarcode=#photo where NetNumber='"+id+"'";
cm2.Parameters.Add("#photo", SqlDbType.Image, personalpic.Length).Value = personalpic;
// here like cursor stop
cm2.ExecuteNonQuery();
lastpage = "x";
File.Delete(Directory.GetCurrentDirectory() + #"\myimage.jpg");
I have run it but nothing happens on query execution I used MessageBox like that to identify the line that has the problem
int refcodenum = getOrderNum();
string refcode = "E" + refcodenum;
byte[] personalpic = getBarcode(refcodenum);
SqlCommand cm2 = new SqlCommand();
cm2.Connection = cn;
MessageBox.Show("1");
cm2.CommandText = "Update Clients set ReferenceNumber='" + refcode + "',ReferenceBarcode=#photo where NetNumber='"+id+"'";
MessageBox.Show("2");
cm2.Parameters.Add("#photo", SqlDbType.Image, personalpic.Length).Value = personalpic;
MessageBox.Show("3");
// here cursor stops
cm2.ExecuteNonQuery();
// that messagebox isn't shown
MessageBox.Show("4");
lastpage = "x";
File.Delete(Directory.GetCurrentDirectory() + #"\myimage.jpg");
Any help will be appreciated
You haven't opened your Connection. See below.
You should also use the using syntax to make use of IDisposable
int refcodenum = getOrderNum();
string refcode = "E" + refcodenum;
byte[] personalpic = getBarcode(refcodenum);
var sqlCmdText = "Update Clients set ReferenceNumber='" + refcode + "',ReferenceBarcode=#photo where NetNumber='"+id+"'";
try
{
using (var sqlConnection = new SqlConnection([YOUR CONNECTION STRING HERE]))
{
using (var sqlCommand = new SqlCommand(sqlCmdText, sqlConnection))
{
sqlCommand.CommandType = CommandType.Text;
sqlCommand.Parameters.Add("#photo", SqlDbType.Image, personalpic.Length).Value = personalpic;
sqlConnection.Open();
sqlCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
throw new DataException(ex.Message);
}

checking if record in database in mysql using c#

Newbie here, I am currently creating a tool that will parse a text file "namelist.txt" contains names. my tool will check if each name are already in my database. if not exist it will write to another file "new_name.log".
my code is something like this.
in my query command I used count(*) to return the count
string DBNAME= "SELECT count(*) FROM tbl_namelist WHERE name = '" + name + "'";
conn.Open();
MySqlCommand DBCmd = new MySqlCommand(DBNAME, conn);
MySqlDataReader reader = DBCmd.ExecuteReader();
while (reader.Read())
{
if (reader == 0)
try
{
//label2.Text = reader.GetString(0);
sds.WriteLine("New Name: " + name+ " " + reader.GetString(0));
}
catch (Exception dd)
{
sds.WriteLine("duplicate Name: " + name+ " " + reader.GetString(0));
}
I dont know if i read the correct info "reader.read" to give me an integer output "count".
please assist me thanks.
don't use MySQLDataReader but instead use command's ExecuteNonScalar to fetch single value.
string DBName = "SELECT count(*) FROM tbl_namelist WHERE name = #name";
using (MySqlConnection conn = new MySqlConnection("connectionString Here"))
{
using (MySqlCommand comm = new MySqlCommand())
{
comm.Connection = conn;
comm.CommandText = DBName;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#name", name);
try
{
conn.Open();
int totalCount = Convert.ToInt32(comm.ExecuteScalar());
if (totalCount == 0)
{
sds.WriteLine("New Name: " + name + " " + totalCount);
}
else
{
// when not zero
}
}
catch( MySqlException ex)
{
// error here
}
}
}
use USING-statement and parameterized your query.
count(*) return int and you should change reader.GetString(0) to reader.GetInt32(0) and in
if(reader==0) to if (reader.GetInt32(0)==0) and it will work

Categories