Invalid attempt to read when no data is present - c#

This is my code:
db.Open();
string updateString = "SELECT TOP 1 RTRIM(kol) kol, RTRIM(adres) adres, RTRIM(numwave) numwave FROM sorters WHERE kodprod=#kodprod AND sorter_kod=#sorter AND moved_ok IS NULL ORDER BY CAST(kol as int)";
try
{
SqlCommand command = new SqlCommand(updateString, db);
//command.Parameters.AddWithValue("#numdoc", NumDoc);
command.Parameters.AddWithValue("#kodprod", KodProd.Id);
command.Parameters.AddWithValue("#sorter", SorterKod);
SqlDataReader reader = command.ExecuteReader();
reader.Read();//here error
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
reader.Close();
}
catch (Exception ex)
{ }
Why do I get this error when I run my code?:
Invalid attempt to read when no data is present

You can check whether the DataReader is ready to fetch the rows
if(reader.HasRows)
{
//do the coding here
}

I believe the error will in fact occur on the next line, viz when you access the reader via the index [] operator. What you need to do is check the result of reader.Read() before accessing it:
if (reader.Read())
{
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
}
Since you are only returning a maximum of one row (TOP 1) there will either be zero or one rows.

you should do a while loop to check reader contain data. You can also use IF if you are sure the query return only one row. If more than one row you should use While. In your case IF also do the job because you are only taking TOP1
string updateString = "SELECT TOP 1 RTRIM(kol) kol, RTRIM(adres) adres,
RTRIM(numwave) numwave FROM sorters WHERE
kodprod=#kodprod AND sorter_kod=#sorter
AND moved_ok IS NULL ORDER BY CAST(kol as int)";
try
{
SqlCommand command = new SqlCommand(updateString, db);
//command.Parameters.AddWithValue("#numdoc", NumDoc);
command.Parameters.AddWithValue("#kodprod", KodProd.Id);
command.Parameters.AddWithValue("#sorter", SorterKod);
SqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
}
reader.Close();
}

Use reader.HasRows
string updateString = "SELECT TOP 1 RTRIM(kol) kol, RTRIM(adres) adres, RTRIM(numwave) numwave FROM sorters WHERE kodprod=#kodprod AND sorter_kod=#sorter AND moved_ok IS NULL ORDER BY CAST(kol as int)";
try
{
SqlCommand command = new SqlCommand(updateString, db);
//command.Parameters.AddWithValue("#numdoc", NumDoc);
command.Parameters.AddWithValue("#kodprod", KodProd.Id);
command.Parameters.AddWithValue("#sorter", SorterKod); SqlDataReader
reader = command.ExecuteReader();
if(reader.HasRows)
while(reader.Read())//here error
{
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
}
reader.Close();
}
catch{}
EDIT: sorry for the bad formatting, posting code from the Android app is a mess.
EDIT: See Microsoft example here

Related

Encountering a System.IndexOutOfRangeException: when trying to display data from two tables in a database

I am writing a form application. User inputs his name, email, address etc into text boxes as if he was ordering a package. If the user has already made an order once I want to make it possible for the user to enter his email into the text box and based on his email fill out all the other personal information needed for the package.
The trouble I am having is that his data is in two different tables. The data which is in customer table (his first and last name) I have successfully retrieved, but the data in the table address I don't know how to get.
Here is the code:
{
try
{
var connection = getConnection();
var command = new SqlCommand
{
Connection = connection,
CommandText = "SELECT * FROM Customer WHERE Email = #Email"
};
command.Parameters.Clear();
command.Parameters.AddWithValue("#Email", mailBox.Text);
connection.Open();
reader = command.ExecuteReader(CommandBehavior.SingleRow);
if (reader.Read())
{
fnameBox.Text = reader["fname"].ToString();
lnameBox.Text = reader["lname"].ToString();
command.CommandText = "SELECT * FROM address WHERE customerID= "+ reader["customerID"].ToString();
stateBox.Text = reader["state"].ToString(); //part where the error happens
cityBox.Text = reader["city"].ToString();
addressBox.Text = reader["address"].ToString();
zipBox.Text = reader["zip"].ToString();
int result = command.ExecuteNonQuery();
connection.Close();
if (result > 0)
{
MessageBox.Show("Success");
}
else
{
MessageBox.Show("Error");
}
}
else
{
MessageBox.Show("E-mail entered doesn't exist");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} ```
Look into using something like EF in future, will clean such things up, but appreciate this is probably not feasible for what you're doing here.
You should get related data from multiple tables via SQL Joins (look into LEFT JOIN and INNER JOIN)
Your problem is caused by the result set not having a state field, which in turn is caused by your not actually executing your SELECT * FROM address query - you are setting the command text but doing nothing further. You need to create another DataReader for the second query and read those results.
Overall there's a lot of stuff to improve, but you're clearly at an early state in learning this so that's fine for now....
you didn't finish to read the first result and after this trying to get the second one
command.Parameters.Clear();
command.Parameters.AddWithValue("#Email", mailBox.Text);
var customerID=0;
var success=false;
connection.Open();
var reader1 = command.ExecuteReader();
if (reader1.Read())
{
sucess=true;
fnameBox.Text = reader1["fname"].ToString();
lnameBox.Text = reader1["lname"].ToString();
customerID= Convert.ToInt32( reader1["customerID"].ToString());
reader1.Close();
}
if( sucess)
{
command.CommandText = "SELECT * FROM address WHERE customerID = #CustomerID";
command.Parameters.Clear();
command.Parameters.AddWithValue("#CustomerID", customerID);
var reader2 = command.ExecuteReader();
sucess=false;
if (reader2.Read())
{
sucess=true;
stateBox.Text = reader2["state"].ToString();
cityBox.Text = reader2["city"].ToString();
addressBox.Text = reader2["address"].ToString();
zipBox.Text = reader2["zip"].ToString();
reader2.Close();
}
if (success)
{
MessageBox.Show("Success");
}
else
{
MessageBox.Show(" address select Error");
}
}
else
{
MessageBox.Show("E-mail entered doesn't exist");
}
connection.Close();

Mysql read and change variable at the same time

I want to shift some variables by one. I searched for the command for it but I couldn't find. If anybody knows it please help me.
Here is the code:
private int shiftNumbers(int number)
{
int newNumber = 0;
string stm = "UPDATE devices SET number= #newNumber WHERE number>#number";
try
{
con.Open();
cmd = new MySqlCommand(stm, con);
cmd.Parameters.AddWithValue("#number", number);
}
catch (Exception e)
{
ErrorMessage = e.Message;
con.Close();
return null;
}
try
{
rdr = cmd.ExecuteReader();
while(rdr.Read()) {
newNumber = rdr.GetInt32(1);
cmd.Parameters.AddWithValue("#newNumber ", (newNumber-1));
}
}
catch (Exception e)
{
ErrorMessage = e.Message;
con.Close();
return null;
}
con.Close();
return 1;
}
I know this code useless but I show it for you to get the logic that I want to do.
I think your approach is wrong.
First, you read from the database, using a select statement;
Then you go over that result, your rdr.Read();
Then you create a new command, updating the original record;
Move forward in your reader (rdr) and repeat from 2 until you are done.
What you are doing now is impossible. You can't get a result set from an update, just a count affected.
Or, if you can, let your update statement do the calculation (it seems it is only subtracting one from the original number, so why not do that in SQL?):
string stm = "UPDATE devices SET number = number - 1 WHERE number>#number";
Yes, your code is really useless. In your update statement you are passing a parameter #newNumber bu not providing it. Closing the connection in catch block.
string stm = "UPDATE devices SET number= #newNumber WHERE number>#number";
First decide from where you are going to get the #newNumber value and then add that as parameter and use ExecuteNonQuery() method.
If you want pass the other parameter as well in your method and use it like
private int shiftNumbers(int number, int newNumber)
{
//int newNumber = 0;
string stm = "UPDATE devices SET number= #newNumber WHERE number>#number";
using(SqlConnection con = new SqlConnection(connectionString))
{
cmd = new MySqlCommand(stm, con);
SqlParameter paramNumber = new SqlParameter("#number", SqlDbType.Int);
paramNumber.Value = number;
SqlParameter paramNewNumber = new SqlParameter("#newNumber", SqlDbType.Int);
paramNewNumber.Value = newNumber;
cmd.Parameters.Add(paramNumber);
cmd.Parameters.Add(paramNewNumber);
con.Open();
cmd.ExecuteNonQuery();
}
//Rest of your code logic if any
}

message error "Specified cast is not valid"

I'm trying to get information from database access with this method
public List<gerant> getinfogerant()
{
List<gerant> gerer = new List<gerant>();
string sql_gerant = "select CIN,NOM,PRENOM,ADRESS_PERSONNEL,NUM_TEL,MAIL,MOBILE,CP_GERANT,VILLE_GERANT,DATE_CIN from GERANT";
connexion connect = new connexion();
OleDbConnection connection = connect.getconnexion();
connection.Open();
OleDbCommand cmd = new OleDbCommand(sql_gerant, connection);
OleDbDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
gerer.Add(new gerant(reader.GetInt64(0),
reader.GetString(1),
reader.GetString(2),
reader.GetString(3),
reader.GetDouble(4),
reader.GetString(5),
reader.GetDouble(6),
reader.GetInt32(7),
reader.GetString(8),
reader.GetDateTime(9))
);
}
connection.Close();
return gerer;
}
In my database access I define the field cin as long integer and formatted "00000000"
But I'm getting an error in reader.GetInt64(0):
Specified cast is not valid
How can I solve that?
Try this code
public List<gerant> getinfogerant()
{
List<gerant> gerer = new List<gerant>();
try
{
connexion connect = new connexion();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = new OleDbConnection(connect.getconnexion());
cmd.CommandType = CommandType.Text;
comd.CommandText = "select CIN,NOM,PRENOM,ADRESS_PERSONNEL,NUM_TEL,MAIL,MOBILE,CP_GERANT,VILLE_GERANT,DATE_CIN from GERANT";
connection.Open();
OleDbDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
gerant g = new gerant();
if (!reader.IsDBNull(0)) g.CIN = int.Parse(reader.GetValue(0).ToString());
if (!reader.IsDBNull(1)) g.NOM = reader.GetValue(1).ToString();
if (!reader.IsDBNull(2)) g.PRENOM = reader.GetValue(2).ToString();
if (!reader.IsDBNull(3)) g.ADRESS_PERSONNEL = reader.GetValue(3).ToString();
if (!reader.IsDBNull(4)) g.NUM_TEL = Convert.ToDouble(reader.GetValue(4).ToString());
if (!reader.IsDBNull(5)) g.MAIL = reader.GetValue(5).ToString();
if (!reader.IsDBNull(6)) g.MOBILE =Convert.ToDouble(reader.GetValue(6).ToString());
if (!reader.IsDBNull(7)) g.CP_GERANT = int.Parse(reader.GetValue(7).ToString());
if (!reader.IsDBNull(8)) g.VILLE_GERANT = reader.GetValue(8).ToString();
if (!reader.IsDBNull(9)) g.DATE_CIN = Convert.ToDateTime(reader.GetValue(9).ToString());
gerer.add(g);
}
return gerer;
}
catch(Exception ex)
{
throw ex;
}
finally
{
reader.Close();
connection.Close();
}
}
and please adjust the names of your classes and methods:
- public List getinfogerant() -> public List getInfoGerant()
connexion connect = new connexion(); -> connection (not x)
Please check for DBNULL values, might be you are getting a null value.
Regards
Jasbeer Singh
Integers in Access come in 1, 2 and 4 byte varieties. The single byte number is named Byte (Range 0-255), the two-byte number is named Integer (-32768 to 32767) and then there is the Long Integer (-2 billion to 2 billion).
https://eggerapps.at/mdbviewer/docs/en/field-types.html
use getint32
I guess, you're getting exception not in the reader.GetInt64(0) but in the gerant constructor, so it could be any column.
To check this modify your code as follows
while (reader.Read())
{
var cin = reader.GetInt64(0);
var nom = reader.GetString(1);
var prenom = reader.GetString(2);
var addressPersonel = reader.GetString(3);
var numTel = reader.GetDouble(4);
var mail = reader.GetString(5);
var mobile = reader.GetDouble(6);
var cpGerant = reader.GetInt32(7);
var villeGerant = reader.GetString(8);
var dateCin = reader.GetDateTime(9);
gerer.Add(new gerant(cin,
nom,
prenom,
addressPersonel,
numTel,
mail,
mobile,
cpGerant,
villeGerant,
dateCin)
);
}
And you will get exception in real line.
I recommend to check column NUM_TEL and MOBILE for double numbers.
Also, check non-string columns for DbNull value before reading. long, int, double and DateTime can not be null.

Invalid attempt to access a field before calling Read()

I'm getting the error:
Invalid attempt to access a field before calling Read()
at: string result = Reader.GetString(0);
I'm not entirely sure what to do or whats wrong though
internal int GetCharGuidByName(string charactername, MySqlConnection connection)
{
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "SELECT guid FROM characters WHERE name=\""+charactername+"\";";
// Initialize MySQL Reader
Reader = command.ExecuteReader();
Reader.Read();
string result = Reader.GetString(0);
// If the character doesn't exist or isn't entered, return 0
int charguid = 0;
if (result != String.Empty)
{
charguid = Convert.ToInt32(result);
}
return charguid;
}
Change the code to:
Reader = command.ExecuteReader();
int charguid = 0;
if(Reader.Read())
{
if(Reader[0] != DBNull.Value)
{
if(int.TryParse(Reader[0].ToString(), out charguid))
{
//value read and is an integer!
}
}
}
return charguid;
You should use ExecuteScalar instead of ExecuteReader
ExecuteSaclar returns the first column of the first row in the result
set, or a null reference
ExecuteReader will return as resultset which you have to then iterate
to read
So looking at your code you just want the first column of the result set
internal int GetCharGuidByName(string charactername, MySqlConnection connection)
{
int charguid = 0;
using(MySqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT guid FROM characters WHERE name=\""+charactername+"\";";
object obj = command.ExecuteScalar();
if (obj != null && obj != DBNull.Value)
{
charguid = Convert.ToInt32(obj);
}
}
return charguid;
}
openConnection()
sql = "SELECT last, first, emp_type, active FROM employee INNER JOIN account ON employee.emp_id = account.emp_id WHERE employee.emp_id = '" & AtxtEmpID.Text & "'"
command = New MySqlCommand(sql, mySqlConnection)
reader = command.ExecuteReader
reader.Read()
AtxtEmpName.Text = reader.Item(0) & ", " & reader.Item(1)
closeConn()
have the save problem

assign data from table to labels using c#

I'm using c# in a ASP.Net web application.I have the following query:
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["chestionar"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("select * from personal,Intrebari where personal.cod_numeric_personal=#cnp AND Intrebari.id_intrebare=14 AND Intrebari.id_intrebare=15 ", con);
cmd.Parameters.AddWithValue("#cnp", Session["sesiune_cnp"]);
SqlDataReader rdr;
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
lbl1.Text = rdr["Nume"].ToString();
intrebare6.Text = rdr["Intrebari"].ToString();
intrebare7.Text = rdr["Intrebari"].ToString();
}
I want those two values for id_intrebare=14 and 15 to assign it to those 2 labels.How can i refer to those?
In order to read stuff from the reader you need to include it in the select statement for you sql, it is better to select it explicitly rather than use select *.
but you are not currently going to get any results returned because id_intrebare cannot be both 14 and 15
you then need to read id_intreabare ratherr than Intreabari.
Try this, notice the try catch block, I also changed your SQL query.
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["chestionar"].ConnectionString);
string qry="select * from personal,Intrebari where personal.cod_numeric_personal=#cnp AND Intrebari.id_intrebare IN (14,15);
SqlCommand cmd = new SqlCommand(qry, con);
cmd.Parameters.AddWithValue("#cnp", Session["sesiune_cnp"]);
try
{
con.Open();
SqlDataReader rdr= cmd.ExecuteReader();
if(rdr.HasRows)
{
while (rdr.Read())
{
lbl1.Text = rdr["Nume"].ToString();
intrebare6.Text = rdr["Intrebari"].ToString();
intrebare7.Text = rdr["Intrebari"].ToString();
}
}
}
catch(SQLException ex)
{
lblStatus.Text="An error occured"+ex.Message;
throw ex;
}
finally
{
con.Close();
con.Dispose();
}
If you want to assign texts to different numbered lables in a loop, you can refer to the control id with FindControl of the current page
int numeOrdinal = reader.GetOrdinal("Nume");
int intrebariOrdinal = reader.GetOrdinal("Intrebari");
int i = 1;
while (rdr.Read()) {
// Nume (Romanian) = Name
page.FindControl("lbl" + i).Text = reader.IsDBNull(numeOrdinal)
? ""
: rdr.GetString(numeOrdinal);
// Intrebari (Romanian) = Question
page.FindControl("intrebari" + i + 5).Text = reader.IsDBNull(intrebariOrdinal)
? ""
: rdr.GetString(intrebariOrdinal);
i++;
}
Try using cmd.ExecuteScalar it will return the first reuslt it finds so you have to define your conditions well. Also it returns object type so you will have to cast the result

Categories

Resources