I'm trying to get data from the SQL Server database but the error state that
System.IndexOutOfRangeException: Index was outside the bounds of the array.
This is my table
TourDisplay
My code:
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=....;Integrated Security=True;Connect Timeout=30;User Instance=True;");
SqlCommand cmd = new SqlCommand();
SqlDataReader dtr;
protected void Page_Load(object sender, EventArgs e)
{
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "select BicycleType from TourDisplay order by TDateTime asc";
dtr = cmd.ExecuteReader();
bool temp = false;
while (dtr.Read())
{
TBBicycleType.Text = dtr.GetString(0);
TBBicycleType2.Text = dtr.GetString(1);
temp = true;
}
}
As you can see, the code should be fine because I got 3 data inside the table but I'm having problem on GetString(1).
It appears that in your select statement, you are selecting ONE column, but in the reader, you're trying to select two.
EXAMPLE: SELECT Id, BicycleType FROM TourDisplay ORDER BY TDateTime
Please either add another column to your select statement, or remove the second selector from the reader:
TBBicycleType2.Text = dtr.GetString(1);
Edit per comment
It appears that you may be trying to set two different buttons, using the first two results from your query with this while reader loop. I'd tweak it a little as follows:
protected void Page_Load(object sender, EventArgs e)
{
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT BicycleType FROM TourDisplay ORDER BY TDateTime";
dtr = cmd.ExecuteReader();
bool temp = false;
// Added this variable. name it anything you like.
bool isFirstItem = true;
while (dtr.Read())
{
// After the first loop iteration, isFirstItem will be set to false
if (isFirstItem)
{
TBBicycleType.Text = dtr.GetString(0);
isFirstItem = false;
}
// All consequent iterations of the loop will set the second
// item's 'Text' property. So if you have only two rows, it
// will be the second row. If you have 20 rows, it will be the 20th row.
else
TBBicycleType2.Text = dtr.GetString(0);
temp = true;
}
}
Although, if you're just setting two buttons using a while loop and from the database, I'd rethink your design a little?
Edit 2 per changes to the OP mentioning 3 total rows in the database
protected void Page_Load(object sender, EventArgs e)
{
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT BicycleType FROM TourDisplay ORDER BY TDateTime";
dtr = cmd.ExecuteReader();
// Again, I'd rethink your design, but if you're just playing
// around this should be fine
int count = 0;
while (dtr.Read())
{
switch (count)
{
case 0:
TBBicycleType.Text = dtr.GetString(0);
break;
case 1:
TBBicycleType2.Text = dtr.GetString(0);
break;
// Add whatever you want to do with the third one here
// case 2:
// TBBicycleType3.Text = dtr.GetString(0);
// break;
}
count++;
}
}
The index is indeed out of bounds. Since you're trying to get the second column on dtr.getString(1). To fix, remove the dtr.getString(1).
In each iteration, dtr.GetString(0) gets the next row of BicycleType. So first iteration, TBBicycleType.Text = "Time Trial". Second iteration, TBBicycleType.Text = "MTB". and so on.
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=....;Integrated Security=True;Connect Timeout=30;User Instance=True;");
SqlCommand cmd = new SqlCommand();
SqlDataReader dtr;
protected void Page_Load(object sender, EventArgs e)
{
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "select BicycleType from TourDisplay order by TDateTime asc";
dtr = cmd.ExecuteReader();
bool temp = false;
while (dtr.Read())
{
TBBicycleType.Text = dtr.GetString(0);
temp = true;
}
}
Related
I created an app like a quiz.. When I try to show the score in the labels I got this error:
An unhandled exception of type 'System.Data.SQLite.SQLiteException' occurred in System.Data.SQLite.dll Additional information: database is locked database is locked
I know which is the problem, but I don`t know how to solve it.
The problem is for sure in the Menu Form (the 'highest parent'). And I know that because the app updates the database from the Quiz form, but when it comes back and read the database so that I can change the labels I got that error. ONLY IF THE update_score() is both in Meniu() (or even in Meniu_Load() ) and after the .ShowDialog()
update_score() -reads database and change labels
Conclusion: I can not show in labels the highest scores both times: when I open the app and when comes back from the quizz form..So, I have to put in comment the update_score after the showdialog (the user won`t know the score when it comes back) or in the Meniu /Meniu_Load (it does not show at the beginning).
How can I solve it?
The Menu code:
public partial class Meniu : Form
{
SQLiteConnection con;
public bool con_opened = false; // tin minte daca am deschis conexiunea
public int bs_lit=0, bs_info = 0;
public Meniu()
{
//this.StartPosition = FormStartPosition.CenterScreen;
InitializeComponent();
con_opened=false;
update_score();
}
private void Meniu_Load(object sender, EventArgs e)
{
//con_opened=false;
//update_score();
}
public void db1_read()
{
if (con_opened == false)
{
con = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;");//Version=3;
con_opened = true;
con.Open();
}
string sql = "select * from bestscore WHERE materie LIKE 'literatura'";
SQLiteCommand command = new SQLiteCommand(sql, con);
SQLiteDataReader reader = command.ExecuteReader();
reader.Read();
bs_lit = Int32.Parse(reader[1].ToString());
command.Dispose();
sql = "select * from bestscore WHERE materie LIKE 'informatica'";
SQLiteCommand cmd = new SQLiteCommand(sql, con);
SQLiteDataReader rdr = cmd.ExecuteReader();
rdr.Read();
bs_info = Int32.Parse(rdr[1].ToString());
cmd.Dispose();
con.Close();
con_opened = false;
}
private void update_score()
{
db1_read();
lbl_bs_info.Text = bs_info.ToString();
lbl_bs_lit.Text = bs_lit.ToString();
}
private void btn_literatura_testare_Click(object sender, EventArgs e)
{
testare flit = new testare();
this.Hide();
flit.reveal = false;
flit.materie = "literatura";
flit.ShowDialog();
update_score(); // if the function is here and in Meniu()
// or Meniu_load()I receive the error
// if it`s just one of them
//it works just fine
if (flit.reveal == true)
this.Show();
else
Application.Exit();
}
}
Thank you!
I found the answer: I didn`t Dispose the readers. Now it works.
public void db1_read()
{
if (con_opened == false)
{
con = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;");//Version=3;
con_opened = true;
con.Open();
}
string sql = "select * from bestscore WHERE materie LIKE 'literatura'";
SQLiteCommand command = new SQLiteCommand(sql, con);
SQLiteDataReader reader = command.ExecuteReader();
reader.Read();
bs_lit = Int32.Parse(reader[1].ToString());
command.Dispose();
reader.Dispose();
sql = "select * from bestscore WHERE materie LIKE 'informatica'";
SQLiteCommand cmd = new SQLiteCommand(sql, con);
SQLiteDataReader rdr = cmd.ExecuteReader();
rdr.Read();
bs_info = Int32.Parse(rdr[1].ToString());
cmd.Dispose();
rdr.Dispose();
con.Close();
con_opened = false;
}
How do I read data in ms access database and display it in a listbox. I have the codes here but i got errors.
private void button3_Click(object sender, EventArgs e)
{
using (OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\Sisc-stronghold\mis!\wilbert.beltran\DataBase\DataStructure.accdb"))
using(OleDbCommand cmd = new OleDbCommand(" SELECT * from TableAcct", conn))
{
conn.Open();
OleDbDataReader Reader = cmd.ExecuteReader();
//if (Reader.HasRows)
if (Reader.HasRows)
{
Reader.Read();
listBox1.Text = Reader.GetString("FirstName");
}
}
the errors are here:
1. Error 1 The best overloaded method match for'System.Data.Common.DbDataReader.GetString(int)' has some invalid arguments.
2. Error 2 Argument '1': cannot convert from 'string' to 'int'
try this one,
List<String> firstName = new List<String>();
List<String> lastName = new List<String>();
private void loadButton_Click(object sender, EventArgs e)
{
cn.Open();
OleDbDataReader reader = null;
cmd = new OleDbCommand("select* from Records", cn);
reader = cmd.ExecuteReader();
while (reader.Read())
{
firstName.Add(reader["FirstName"].ToString());
lastName.Add(reader["LastName"].ToString());
}
cn.Close();
}
then in your search button, insert this,
private void searchButton_Click(object sender, EventArgs e)
{
clearSearchResult();
try
{
int totalItems = FirstName.Count;
int count = 0;
while (count < totalItems)
{
if (textBox6.Text == FirstName[count].ToString())
{
listBox1.Items.Add(FirstName[count].ToString());
count = 100;
}
else
{
count++;
}
It's good to use when you want to show the information of the "FirstName" in the listBox1_SelectedIndexChanged if you want. here's an example,
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int totalItems = lastName.Count;
int count = 0;
while (count < totalItems)
{
if ((listBox1.SelectedItem.ToString()) == firstName[count].ToString()))
{
textBox1.Text = firstName[count].ToString();
textBox2.Text = lastName[count].ToString();
count = 100;
}
else
{
count++;
}
}
hope this helps,
change
listBox1.Text = Reader.GetString("FirstName");
to
listBox1.Text = Reader.GetString(0); // zero base ordinal of column
GetString() takes an int as the parameter and not a string. Meaning that you must use the index of the column.
In your specific circumstance as "FirstName" is the second column the index would be 1:
listBox1.Text = Reader.GetString(1);
http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbdatareader.getstring.aspx
Thy using a While loop
while(reader.Read())
{
listbox1.Items.Add(reader["FirstName"]);
}
This moves through all the rows you selected. reader.Read() returns false if there are no more rows.
Also: if you Want to retrive valmue from a column I suggest you do it with the index ón the reader instance. Like my example.
var value = reader["ColumnName"];
This increases readability comparing to
var value = reader.GetString(0);
UPDATE
If you want to only display the fist value - I suggest you use cmd.ExecuteScalar() and the adapt you sql to only return the value you need:
using(OleDbCommand cmd = new OleDbCommand("SELECT firstname from TableAcct", conn))
{
conn.Open();
var firstName = cmd.ExecuteScalar();
}
Be aware the this will give you the first "FirstName" in the table. And since there is no "order by firstname" or "where someKey = 1" - this might not rturn that you expected.
If you want to create MS Access data base and to access it, and to display data in some component, like here i will show you.how to connect with MS Access Data Base and display data from data base in Label.
First of all create any Access data base like here "PirFahimDataBase".
Now in your Visual Studio go to the menu and do this
Click Data
Add New Data Base
Click Next
Click New Connection
Now change the Data Source by clicking Change and select Microsoft Access data base files
Click Browse for selecting your created data base
Now in Button ClickEvent paste these code which will get data from data base and will show it in the label
using System.Windows.Forms; //these two lines should be written before namespace at top of the program
using System.Data.OleDb;
private void button1_Click(object sender, EventArgs e)
{
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data source= C:\Users\pir fahim shah\Documents\PirFahimDataBase.accdb";
try
{
conn.Open();
MessageBox.Show("connected successfuly");
OleDbDataReader reader = null; // This is OleDb Reader
OleDbCommand cmd = new OleDbCommand("select TicketNo from Table1 where Sellprice='6000' ", conn);
reader = cmd.ExecuteReader();
while (reader.Read())
{
label1.Text= reader["TicketNo"].ToString();
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to connect to data source");
}
finally
{
conn.Close();
}
}//end of button click event
Your error is in this line:
listBox1.Text = Reader.GetString("FirstName");
You must pass a number in the GetString() function.
DataColumn[] PrimaryKeyColumn = new DataColumn[1]; //Define Primary coloumn
DataSet dataSet = new DataSet();
DataTable dataTable = new DataTable();
ReadAndUpdateExcel.ReadExcel(strPath, sheetName, out dataSet);
dataSet.Tables.Add(dataTable);
PrimaryKeyColumn[0] = dataSet.Tables[0].Columns[0];
dataSet.Tables[0].PrimaryKey = PrimaryKeyColumn;
string num = dataSet.Tables[0].Rows[dataSet.Tables[0].Rows.IndexOf(dataSet.Tables[0].Rows.Find(strTCName))]["ACNO"].ToString();
//string country
This is my code:
private void CostList_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'lSEStockDataSet.CostPrice' table. You can move, or remove it, as needed.
this.costPriceTableAdapter.Fill(this.lSEStockDataSet.CostPrice);
con = new System.Data.SqlClient.SqlConnection();
con.ConnectionString = "Data Source=tcp:SHEN-PC,49172\\SQLEXPRESS;Initial Catalog=LSEStock;Integrated Security=True";
con.Open();
DataGridView datagridview1 = new DataGridView();
String retrieveData = "SELECT CostID, SupplierName, CostPrice FROM CostPrice WHERE PartsID ='" + textBox1.Text + "'";
SqlCommand cmd = new SqlCommand(retrieveData, con);
int count = cmd.ExecuteNonQuery();
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
dataGridView1.DataSource = dt;
con.Close();
}
private void button1_Click(object sender, EventArgs e)
{
if (dataGridView1.Rows.Count > 0)
{
int nRowIndex = dataGridView1.Rows.Count-1;
if (dataGridView1.Rows[nRowIndex].Cells[2].Value != null)
{
textBox2.Text = Convert.ToString(dataGridView1.Rows[nRowIndex].Cells[2].Value);
}
else
{
MessageBox.Show("NULL");
}
}
}
It shows NULL when i clikc the button, what is the problem here? I have 3 columns there, i want to get the data of the 3rd column of the last row, but it shows NULL but there is data in the specified cell. Anyone knows how to solve this problem?
Instead of subtracting one from the row count, try subtracting two. Subtracting one is giving you the zero-based index of the "add" row, which indeed has a null value in the last column.
int nRowIndex = dataGridView1.Rows.Count-2;
By subtracting 2 from the count, you will get the zero-based index of the last row with actual data in it. I think this is what you are looking for.
As an aside, you will likely want to parameterize your SQL query, something like this:
String retrieveData = "SELECT CostID, SupplierName, CostPrice FROM CostPrice WHERE PartsID = #inPartsID";
SqlCommand cmd = new SqlCommand(retrieveData, con);
cmd.Parameters.Add(new SqlParameter("#inPartsID", textBox1.Text));
This will make your query more reliable (what happens if there is a single quote character in textBox1) and your data more secure (evil-doers can use SQL injection to cause harm to your database or get data out of it that they shouldn't).
Please take a look at the following code.
protected void Button2_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(constring);
SqlCommand cmd = new SqlCommand();
if (DropDownList3.SelectedItem.Text == "Economy")
{
seats = Convert.ToInt32(DropDownList1.SelectedItem.Text);
cmd.Connection = con;
con.Open();
cmd.CommandText = "select easeats from flight where fno='" + fn + "'";
int eds = Convert.ToInt32(cmd.ExecuteScalar());
if (eds > seats)
{
Panel2.Visible = true; //seats available
cl = DropDownList3.SelectedItem.Text;
seat = seats.ToString();
seats = eds;
}
else
{
Panel3.Visible = true; // seats not available
}
con.Close();
}
}
I am getting error in the line:int eds = Convert.ToInt32(cmd.ExecuteScalar());
And the error is
error in converting varchar value to datatype int
What is wrong with this code?
Firstly, NEVER construct your query like this. Use parameterized queries instead.
Secondly, the error message is quite clear - you're trying to convert to int some varchar column, that probably contains some literal characters as well and not only numbers...
Thirdly, prefer "using" statements over explicitly closing the connection. It's more safe that way.
try to replace:
int eds = Convert.ToInt32(cmd.ExecuteScalar());
with:
int eds = 0;
int.TryParse(cmd.ExecuteScalar(), out eds);
in this way if the Convert fails you have no issues and continue with eds = 0...
side note, your handling of exceptions and connection lifetime is very poor, think about replacing the whole block in this way:
protected void Button2_Click(object sender, EventArgs e)
{
using(var con = new SqlConnection(constring))
using(var cmd = con.CreateCommand())
{
if (DropDownList3.SelectedItem.Text == "Economy")
{
seats = Convert.ToInt32(DropDownList1.SelectedItem.Text);
con.Open();
cmd.CommandText = "select easeats from flight where fno='" + fn + "'";
int eds = 0;
object result = cmd.ExecuteScalar();
int.TryParse(result, out eds);
if (eds > seats)
{
Panel2.Visible = true; //seats available
cl = DropDownList3.SelectedItem.Text;
seat = seats.ToString();
seats = eds;
}
else
{
Panel3.Visible = true; // seats not available
}
}
}
}
of course, anyway, you should also consider to refactor the whole thing and separate clearly database and business logic from UI logic, in general you should never deal directly with connections and queries inside the UI and even less in a ButtonClick event handler.
I have the label:
<asp:Label ID="lbl1" runat="server"></asp:Label>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
lbl1.Text = ImageCheck().ToString();
}
And:
protected int ImageCheck()
{
SqlConnection connection = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\***.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True");
string CommandText2 = "SELECT * FROM Machreta WHERE noImage = 1";
SqlCommand command2 = new SqlCommand(CommandText2, connection);
connection.Open();
int check = (int)command2.ExecuteScalar();
connection.Close();
return check;
}
How can i return multiple values? That label display only single value but there are 6 more in the table.
try this:
protected string ImageCheck()
{
var result = new StringBuilder();
using(var connection = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\***.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"))
{
string CommandText2 = "SELECT * FROM Machreta WHERE noImage = 1";
SqlCommand command2 = new SqlCommand(CommandText2, connection);
connection.Open();
using(var reader = command2.ExecuteReader())
{
while (reader.Read())
{
result.Append(reader.GetString(0));
}
}
return result.ToString();
}
}
of course is only an example and not fully solving your issue but should be a starting point :)
Here is the explanation of ExecuteScalar() method. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar%28v=vs.71%29.aspx
"Executes the query, and returns the first column of the first row in the result set returned by the query. Extra columns or rows are ignored."
Also, SELECT * will fetch all the columns. You probably want to display multiple values for single column. Then select the column name in select statement.
SELECT xyzColumn FROM Machreta WHERE noImage = 1
Lastly, you can assign only one string to label.text. So, you will have to concatenate all these strings (multiple values for single column) and then assign it to label text. Use a reader and ExecuteReader() method instead of ExuecuteScalar().