I'm trying to take from a DataBase all under aged users, but when I try to, System.InvalidOperationException: 'Connection must be valid and open.'
pops up. It's a Windows Form app, so this happens when I press the button.
I have tried searching for the problem but I cant find the error. I have 5 more functions with the same syntax and they work just fine. This is the code I have:
public static List<User> Underage(MySqlConnection connection)
{
string query= string.Format("SELECT * FROM users WHERE age<18");
MySqlCommand command = new MySqlCommand(query, connection);
MySqlDataReader reader = command.ExecuteReader();
List<User> underage= new List<User>();
if (reader.HasRows)
{
User usu = new User();
while (reader.Read())
{
usu.id = reader.GetInt16(0);
usu.name = reader.GetString(1);
usu.surname= reader.GetString(2);
usu.email = reader.GetString(3);
usu.age= reader.GetInt16(4);
usu.birth = reader.GetDateTime(5);
usu.payment= reader.GetFloat(6);
underage.Add(usu);
}
}
return underage;
}
Thanks anyways and sorry if it's a stupid problem, but I just cant figure it out.
Thanks for clarifying my problem mjwills and Adyson, you were right, I forgot to open it. I have a function to open the connection which I used in every other method of my program but I forgot to add it in this one. Sorry and thank you!
Related
I am running a C# windows application, and I get an error message when trying to use a datareader. The error message is:
"Invalid attempt to call CheckDataIsReady when reader is closed."
I used stop point and saw that the code works fine until it enters the "while" loop. Once inside, it gives the error message.
I have tried to do it without closing the previous reader, but then the message changed to something like "there is already an open reader" or some such.
Here's the code:
conn = new SqlConnection(DBConnectionString);
SqlCommand select_cmd = new SqlCommand("SELECT usrRealname, usrIsowner FROM tblUSERS WHERE usrNum = " + UserID, conn);
SqlCommand select_orders = new SqlCommand("SELECT orderNum, orderBy, orderShipadrs, orderDate, orderTotal FROM tblOrders WHERE orderDeliveryDate is NULL AND fkorderTakenbyusrnum = " + UserID, conn);
conn.Open();
SqlDataReader dr = select_cmd.ExecuteReader();
dr.Read();
CurrentUser User = new CurrentUser(Convert.ToString(dr[0]), UserID, Convert.ToBoolean(dr[1]));
DetailsLabel.Text = String.Format("Welcome {0}, ID number {1}. {2}", User.getname, UserID, User.getOwner);
dr.Close();
SqlDataReader orders = select_orders.ExecuteReader();
while (orders.Read())
{
UnfulfilledOrders CurrentOrder = new UnfulfilledOrders(Convert.ToInt32(dr[0]), Convert.ToString(dr[1]), Convert.ToString(dr[2]), Convert.ToString(dr[3]), Convert.ToInt32(dr[4]));
OrderList.Items.Add(CurrentOrder);
}
What I'd trying to do is add class (UnfulfilledOrders) type objects to a listbox (OrderList).
The thing that baffles me is that I used such a while loop in a previous form in the same app, and it worked fine there.
I really have no idea what I'm doing wrong.
I tried twiking the code, adding or removing certain parts, but nothing seems to work.
Your problem is that in your while loop you're using dr[0] instead of orders[0]. This is trying to get the value from the SqlDataReader dr.
A good way to avoid mix-ups like this would be to create the data reader in a using block.
using (var dr = select_cmd.ExecuteReader())
{
//your code here
dr.Close();
}
then
using (var orders = select_orders.ExecuteReader())
{
// your code here
orders.Close();
}
This would prevent you from accidently referencing the wrong reader because VS would give you an error saying it doesn't exist.
Your code:
dr.Close(); //<-- dr closed
SqlDataReader orders = select_orders.ExecuteReader(); // <-- Reader is "orders" here
while (orders.Read())
{
UnfulfilledOrders CurrentOrder = new UnfulfilledOrders(Convert.ToInt32(dr[0]), Convert.ToString(dr[1]), Convert.ToString(dr[2]), Convert.ToString(dr[3]), Convert.ToInt32(dr[4]));
OrderList.Items.Add(CurrentOrder);
}
dr was closed previously, do you mean "orders" instead of "dr"?
I'm having problems with updating a row in the Users table of my Access DB. Here is the code below:
private void SaveProfileInfo()
{
try
{
ChangeForeColorOfStatusMsg(Color.Black);
ChangeTextOfStatusMsg("Saving new profile information...");
const string cmd = #"UPDATE Users SET LastName=#LastName,FirstName=#FirstName,MiddleName=#MiddleName,Add_Num=#Add_Num,Add_Street=#Add_Street,Add_Brgy=#Add_Brgy,Add_City=#Add_City,MobileNumber=#MobileNumber,Gender=#Gender WHERE ID=#ID;";
var dbConn = new OleDbConnection(cs);
var dbCmd = new OleDbCommand(cmd, dbConn);
dbCmd.Parameters.AddWithValue("#ID", UserLoggedIn.ID);
dbCmd.Parameters.AddWithValue("#LastName", txtLastName.Text);
dbCmd.Parameters.AddWithValue("#FirstName", txtFirstName.Text);
dbCmd.Parameters.AddWithValue("#MiddleName", txtMiddleName.Text);
dbCmd.Parameters.AddWithValue("#Add_Num", txtUnitNum.Text);
dbCmd.Parameters.AddWithValue("#Add_Street", txtStreet.Text);
dbCmd.Parameters.AddWithValue("#Add_Brgy", GetBrgySelectedItem());
dbCmd.Parameters.AddWithValue("#Add_City", GetCitySelectedItem());
dbCmd.Parameters.AddWithValue("#MobileNumber", txtMobileNumber.Text);
dbCmd.Parameters.AddWithValue("#Gender", GetGenderSelectedItem());
dbConn.Open();
dbCmd.ExecuteNonQuery();
dbConn.Close();
ChangeForeColorOfStatusMsg(Color.MediumSeaGreen);
ChangeTextOfStatusMsg("All changes have been saved! This window will close itself after two seconds.");
Thread.Sleep(2000);
CloseForm();
}
catch (Exception)
{
ChangeForeColorOfStatusMsg(Color.Crimson);
ChangeTextOfStatusMsg("Something went wrong while we were connecting to our database. Please try again later.");
hasFinishedEditting = false;
}
}
This method will be done on a separate thread, when the user updates his profile information.
UserLoggedIn is actually a field of a User class (a class that defines a row in my table), which stores all the info of the user who's currently logged in.
When I run this, it does not produce any exceptions or errors. But when I check my table, the values are not updated.
I copy-pasted these codes from the registration form (which works) that I made with this system, and modified it into an UPDATE cmd than an INSERT cmd.
I also made Change Username and Password Forms that use the same cmd as shown below:
public void ChangePass()
{
try
{
ChangeForeColorOfMsg(Color.Silver);
ChangeTextOfMsg("Changing password...");
const string cmd = "update Users set Pass=#Pass where ID=#ID";
var dbConn = new OleDbConnection(cs);
var dbCmd = new OleDbCommand(cmd, dbConn);
dbCmd.Parameters.AddWithValue("#Pass", txtNewPass.Text);
dbCmd.Parameters.AddWithValue("#ID", UserLoggedIn.ID);
dbConn.Open();
dbCmd.ExecuteNonQuery();
dbConn.Close();
ChangeTextOfMsg("Password successfully changed!");
}
catch (Exception)
{
ChangeForeColorOfMsg(Color.Silver);
ChangeTextOfMsg("A problem occurred. Please try again later.");
}
}
And these codes work for me. So I'm really confused right now as to why this update cmd for the profile information isn't working... Is there something I'm not seeing here?
OleDb cannot recognize parameters by their name. It follows a strictly positional order when sending them to your database for updates. In your code above the first parameter is the #ID but this parameter is used last in your query. Thus everything is messed up.
You just need to move the add of the #ID parameter as last in the collection
As a side note, you should be very careful with AddWithValue. It is an handy shortcut, but it has a dark side that could result in wrong queries.
Take a look at
Can we stop using AddWithValue already?
I am making a simple voting system, that when a voter is already done voting and tries to re-log in, the system will read the database and stop the voter from logging in. How can I do that?
What I have in my database :
username, password and remarks. remarks is when a voter is "Done" or "Not Voted".
What I have in my code now :
conn.Open();
SqlCommand cmd;
SqlDataReader dr;
string cmdall = "Select from Voter where username=#user and password=#pass and remarks=''"; //got no clue as to what i am going to command here..
using (cmd = new SqlCommand(cmdall, _db._conn))
{
cmd.Parameters.AddWithValue("#user", _user);
cmd.Parameters.AddWithValue("#pass", _pass);
dr = cmd.ExecuteReader();
/* Then if and else statement */
}
Please help me out, im kinda new at this.. Thanks in advance..
You query should be like:
string cmdall = "Select remarks from Voter where username=#user and password=#pass";
and then check it's value is Done :
while(dr.Read())
{
if (dr["remarks"].ToString() == "Done")
// already voted
}
as #Daniel pointed in comments better would be to use bit in database because it's suitable in your case , there is only two chances true or false
Hello I create controls from SQL via this code:
string query = "SELECT * FROM [schema] WHERE idSch=#id";
SqlCommand com = new SqlCommand(query, con);
com.Parameters.AddWithValue("#id", result);
con.Open();
SqlDataReader read= com.ExecuteReader();
while (read.Read())
{
createLabelCmd((int)read["x"], (int)read["y"]);
}
con.Close();
The issue is that createLabelCmd contains SqlCommand and it needs an open SqlConnection
Inside createLabelCmd
String ResultSitting
private void createLabelCmd(int x, int y)
{
for (int i = 0; i < 1; i++)
{
var newLabel = new Label();
newLabel.Location = new Point(x, y);
newLabel.Text = realpocsed.ToString();
string sitting = newLabel.Name;
string sittingSearch = (sitting).Substring(3, 1);
if (sittingSearch != null && kzajezdu == "kZajezdu")
{
string querySitting = "SELECT name, surname FROM klient WHERE sitting = #sitting AND event=#event AND year=#year";
SqlCommand cmdSitting = new SqlCommand(querySitting, spojeni);
cmdSitting.Parameters.AddWithValue("#sitting", sittingSearch);
cmdSitting.Parameters.AddWithValue("#event", idEvent);
cmdSitting.Parameters.AddWithValue("#year", klientClass.Year());
ResultSitting = cmdSitting.ExecuteScalar().ToString().Trim(); //This might be the issue
}
if (kzajezdu == "kZajezdu")
{
newLabel.MouseHover += delegate(object sender, EventArgs e)
{
ToolTip ToolTip1 = new ToolTip();
ToolTip1.ShowAlways = true;
if (sittingSearch != null)
{
ToolTip1.Show(ResultSitting, newLabel);
}
else { ToolTip1.Show("This sitting is Empty!", newLabel); }
};
}
panel1.Controls.Add(newLabel);
}
I get an Exception: InvalidOpearationException: There is already an open DataReader associated with this Command which must be closed first.
May you please help me solve this out?
Edit as Soner Gönül suggested:
try
{
string query = "SELECT * FROM [schema] WHERE idSch=#id";
SqlCommand com = new SqlCommand(query, con);
com.Parameters.AddWithValue("#id", idSch);
con.Open();
SqlDataReader read= com.ExecuteReader();
while (precti.Read())
{
createLabelCmd((int)read["x"], (int)read["y"]);
}
con.Close();
}
The cause of the problem is outlined in other answers (while a DataReader is open, the connection used by that reader cannot serve other commands), however many fails to talk about MultipleActiveResultSets that has been introduced for this kind of situations
Just change your connection string to include this option and your code will work without any change
Server=yourServer;Database=yourDB;Trusted_Connection=True;MultipleActiveResultSets=true;
To complete the answer, MARS is available starting from SQL Server 2005 and there are minor problems that you should be aware of.
Because when you while loop with your open SqlDataReader, there is an open connection already.
From DataReaders (ADO.NET)
“You can use the ADO.NET DataReader to retrieve a read-only,
forward-only stream of data from a database.
Results are returned as the query executes, and are stored in the
network buffer on the client until you request them using the Read
method of the DataReader”
As a general recomendation, use using like;
using(SqlDataReader read= com.ExecuteReader())
{
while (read.Read())
{
createLabelCmd((int)read["x"], (int)read["y"]);
}
}
Or set this in your connection string;
...MultipleActiveResultSets=true;
I guess you are writing a sitting planner and try to show labels at specific positions. Therefore, you would better select all records from klient table for a given event and put them in a DataSet. Then iterate through it (using a foreach) and create the labels. This way, there is only ONE command that should be sent to database and , obviously, the performance of your application will be much better.
Having said that, I don't understand how your sittingSearch variable work and I think it needs revising.
You can either use a 2nd connection for createLabelCmd or turn on MARS (multiple active results sets) in your initial connection by adding "MultipleActiveResultSets=True" to your connection string.
http://msdn.microsoft.com/en-us/library/h32h3abf.aspx
Setting MARS to True AND
making sure i used ToList(); in my if statements and returns
in the below code i was missing the toList() in both conditions of the if statement, i was getting the error on IIS 8.5 after publishing .. updating the statement to the below worked#!
var varM = (id == 1) ? db.M.Where(x => x.UN== userID).ToList() : db.M.Where(x => x.EUN== userID).ToList();
Here's the crux of it:
I have this script which gave me absolutely no problems until after I ran it through a performance test, and now its' constantly showing me the same error during debug whenever I try to run it:
using (OracleConnection con = new OracleConnection())
{
//Connect to OracleDB and retreive the first valid, unused SRVID//
con.ConnectionString = #"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=myhostip)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=MyServerNAme)));User Id=MyUSer;Password=MyPAssword";
OracleCommand command = new OracleCommand("SELECT MASK_GUID(SWAP_GUID(SRVID)) FROM MYTable WHERE USED=0 AND ROWNUM = 1", con);
con.Open();
OracleDataReader reader = command.ExecuteReader();
reader.Read();
ServerID = reader.GetString(0);
reader.Close();
//update SRVID in DB as used so further users will not select it
command.CommandText = "UPDATE MyTable SET USED=1 WHERE SRVID = FIX_GUID('"+ ServerID+"')";
command.Connection = con;
command.ExecuteNonQuery();
reader.Close();
reader.Dispose();
con.Close();
con.Dispose();
}
That's the code, here's what goes wrong:
on ServerID= reader.GetString(0) I receive the operation is not valid due to the current state of the object error. When glossing over reader in debug, I see that it has no data rows, which might explain the error (but that leads to...)
The query is fine. I run it locally on the database and it returns a valid value ( I copy-pasted it to be sure), so that's not the reason reader has no data.
This problem started during a performance test which ran this script about 800 times before this error started to appear constantly... The system which I tested still operates fine, even when performing actions that require access to the same database.
Debugger shows no other errors regarding this case... OR at all, for that matter.
Ideas?
You need to set the MaxHttpCollection property to a higher value.