I have the following code in C#:
string query = "SELECT * FROM Zboruri WHERE cod_aeroport = " + country;
using (var command = new SqlCommand(query, connection))
{
var list = new ArrayList();
var reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
string data1 = reader.GetString(1);
string data2 = reader.GetString(2);
list.Add(cod_aeroport);
list.Add(data1);
list.Add(data2);
}
}
else
{
string raspuns = "nu este info";
list.Add(raspuns);
}
reader.Close();
connection.Close();
return list;
}
My database table has these columns:
data1(numeric(18,0))
data2(numeric(18,0))
...........
and it giving me error:
Index was outside the bounds of the array.
on this line of code:
string data2 = reader.GetString(2);
How can I fix error?
index starts at 0, not 1
string data1 = reader.GetString(0);
string data2 = reader.GetString(1);
I'll prefer to use the column names retrieve from the table because it gives more description than using index of the column (which is usually the reason for index out of bounds exception)
ex,
string data1 = reader["colName1"].ToString();
string data2 = reader["colName2"].ToString();
side-note: please do use parameters in your query,
string query = "SELECT * FROM Zboruri WHERE cod_aeroport = #country";
and before you call ExecuteReader add this line,
command.Parameters.AddWithValue("#country", country);
var reader = command.ExecuteReader();
The index is zero based, so the first column is 0, the second is 1. You should really use the named version of the columns though;
string data1 = reader["data1"].ToString();
One more thing, you should probably parameterize your query to avoid SQL injection problems, in this case it's almost as simple as your original query and much safer. It also helps the database save quite a bit of time and memory on similar queries;
string query = "SELECT * FROM Zboruri WHERE cod_aeroport = #country";
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("#country", country);
var list = new ArrayList();
...
You should better access them by name, by resolving the index by name using the GetOrdinal() method first, so that the code doesn't break if the query is extended later.
if (reader.HasRows)
{
int data1Index = reader.GetOrdinal("data1");
int data2Index = reader.GetOrdinal("data2");
while (reader.Read())
{
string data1 = reader.GetString(data1index);
string data2 = reader.GetString(data2index);
list.Add(cod_aeroport);
list.Add(data1);
list.Add(data2);
}
}
Note that this is the slightly better approach compared to using the named indexer because it avoids looking up the index on every row.
Also, please do parametrize the query to avoid SQL injection.
Related
I'm working on a project where the customer can make an order of infinite products, I need my code to read every single product ID of his order.
For this to work, it needs to be in a loop, and I could only find ways to make this without a loop, with finite products on the internet.
I tried using SELECT like this:
string selectCod = "SELECT id FROM order";
MySqlCommand selectCodCmd = new MySqlCommand(selectCod, BDconnection);
reader = selectCodCmd.ExecuteReader();
while (reader.Read())
{
}
reader.Close();
But I can't think of anything to put inside the while, I tried using x = reader[0].ToString(); but I only get the last product ID.
If anyone could help me I would appreciate it
Edit1:
Thanks a lot, It worked! Here's the code if anyone has the same problem in future:
string selectCod = "SELECT id FROM OrderItens";
var selectCodCmd = new MySqlCommand(selectCod, BDconnection);
reader = selectCodCmd.ExecuteReader();
var OrderItensId = new List<string>();
while (reader.Read())
{
OrderItensId.Add(reader["id"].ToString());
}
reader.Close();
foreach(string Code in OrderItensId)
{
string CodeAmount = "SELECT amount FROM OrderItens
WHERE id = "+ Code +"";
var CodeAmountCmd = new MySqlCommand(CodeAmount, BDconnection);
reader = CodeAmountCmd.ExecuteReader();
int OrderAmount = 0;
while (reader.Read())
{
OrderAmount = Int32.Parse(reader[0].ToString());
}
reader.Close();
string UpdateStock = "UPDATE Stock
SET amount = amount - "+OrderAmount+"
WHERE id = "+ Code +"";
var UpdateStockCmd = new MySqlCommand(UpdateStock, BDconnection);
reader = UpdateStockCmd.ExecuteReader();
while (reader.Read()) { }
reader.Close();
}
Well, as i understand, you need to get all the products ids from one specific order right?
With this, you only getting all the orders ids from your table orders
string selectCod = "SELECT id FROM order";
First, you will need the order id and i suppose that you have a table called orderItens or something like that..
Then, you get all the itens for that order with a select like this:
string selectCod = "SELECT id FROM orderItens where orderId = #orderId";
Then just create a loop like this
var orderItensIds = new List<int>();
while (reader.Read())
{
orderItensIds.Add(int.Parse(reader["id"]));
}
reader.Close();
return orderItensIds
There you have a list with all the itens id from your order
You are using it right, you just need to put the code var x = reader[0].ToString(); into while loop to let it get all id in all rows.
For example, I will use a listId list to save Id list. You can use it to calculate or insert later.
string selectCod = "SELECT id FROM order";
MySqlCommand selectCodCmd = new MySqlCommand(selectCod, BDconnection);
reader = selectCodCmd.ExecuteReader();
var listId = new List<int>();
while (reader.Read())
{
var x = reader[0].ToString();
listId.Add(int.Parse(x));
}
reader.Close();
// Use this list to any where you want
listId
I am using the following Access query on C# MVC to compare two tables and return records that fall within the date range and machine selected by the user. The query code runs perfectly on the actual Access database but I guess something is wrong with the connection string and the code to return the results. I am not sure what's wrong with the code and I would appreciate if someone could help me determine what's wrong. Thanks!
C# MVC Controller code:
public ActionResult MissingChecksheets(string startDate, string endDate, string machine)
{
var query = $#"SELECT * FROM [TrackingLog]
WHERE [TrackingLog].[Workcenter] = '{machine}' AND
[TrackingLog].[Complete Date] > #{startDate}# AND
[TrackingLog].[Complete Date] < #{endDate}# AND
[TrackingLog].[Order Item] NOT IN (SELECT [OrderNum] FROM [dbo_Checksheet])";
var sheets = new List<Checksheet>();
using (var con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Checksheets.accdb;"))
{
using (var command = new OleDbCommand(query, con))
{
con.Open();
using (var reader = command.ExecuteReader())
{
while (reader.NextResult())
{
sheets.Add(new FabChecksheet
{
OrderNum = reader.GetString(0),
PartNum = reader.GetString(1)
});
}
}
}
}
return PartialView(sheets);
}
OleDbDataReader.NextResult() method used to move between result set if the query string has multiple result sets (e.g. more than two SELECT statements, not counting SELECT inside aggregate functions). Since your query has single result set, OleDbDataReader.Read() must be used to move between records:
using (var con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Checksheets.accdb;"))
{
using (var command = new OleDbCommand(query, con))
{
con.Open();
using (var reader = command.ExecuteReader())
{
// Only single result set, use 'Read' here
while (reader.Read())
{
sheets.Add(new FabChecksheet
{
OrderNum = reader.GetString(0),
PartNum = reader.GetString(1)
});
}
}
}
}
Note that if NextResult() is used, the data reader will move to next result set which has empty data.
Related issue:
Difference between SqlDataReader.Read and SqlDataReader.NextResult
My variable names, database tables are right, I get error like this;
MySql.Data.MySqlClient.MySqlException: 'There is already an open DataReader associated with this Connection which must be closed first.'
public string urun_adi_bul(string urun_id)// find product name
{
if (genel.baglanti.State == ConnectionState.Closed)
{
genel.baglanti.Open();
}
string urun_adi = "";
genel.sqlgonder.Connection = genel.baglanti;
genel.sqlgonder.CommandText = "Select * from urunler where urun_id="+urun_id;
MySqlDataReader oku = genel.sqlgonder.ExecuteReader();
while (oku.Read())
{
urun_adi = oku["urun_id"].ToString();
}
oku.Close();
return urun_adi;// product name
}
public void hesapGetir(ListView lvSiparis, string masa_id)
{
genel.baglanti.Open();
MySqlCommand sqlgonder = new MySqlCommand();
sqlgonder.Connection = genel.baglanti;
sqlgonder.CommandText = "Select * from adisyonlar where masa_id = "+masa_id;
MySqlDataReader oku = sqlgonder.ExecuteReader();
lvSiparis.Items.Clear();
string urun_adi = "",urun_id="";
while (oku.Read())
{
urun_id = oku["urun_id"].ToString();
decimal fiyat = Convert.ToDecimal(urun_fiyati_bul(urun_id)); // price
decimal adet = Convert.ToDecimal(oku["urun_adet"]); // piece
decimal toplam = fiyat * adet; // total
urun_adi = urun_adi_bul(urun_id);
ListViewItem item = new ListViewItem(urun_adi);
item.SubItems.Add(adet.ToString());
item.SubItems.Add(toplam.ToString());
lvSiparis.Items.Add(item);
}
oku.Close();
genel.baglanti.Close();
}
How can I use 2 datareaders in a loop?
You can have only one open reader (or any kind of query) per connection. But you actually only need one reader if you combine the two queries with a JOIN:
SELECT adisyonlar.urun_id, urun_adet, urunler.urun_id
FROM adisyonlar
LEFT JOIN urunler
ON adisyonlar.urun_id = urunler.urun_id
This way you let the db do the work to find the matching records, and you only need one query instead of asking the db again and again for every row in adisyonlar.
Note that it's better practice to explicity name the columns you want to fetch instead of fetching all columns with SELECT *.
Plus: your queries are open to SQL injection! Please use parameterized queries.
I know I can use while (dr.Read()) {...} but that loops every field on my table, I want to retrieve all the values from the first row, and then second... and so on.
Let's say I have a table like this:
ID--------------Value1--------------Value2------------------Value3
1 hello hello2 hello3
2 hi1 hi2 hi3
3 hey1 hey2
I want output as : hello hi1 hey1
From the comment below:
flag
SqlCeCommand cmd = new SqlCeCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select * From DataLogger1 where Time BETWEEN '"+DateTimePicker.Value+"' AND '"+DateTimePicker1.Value+"' ";
cmd.Connection = conn1;
conn1.Open();
SqlCeDataReader rd= cmd.ExecuteReader();
while(rd.Read())
{
Globals.Tags.Xarrray[0].Value=rd[2].ToString();
Globals.Tags.Xarrray[1].Value=rd[2].ToString();
Globals.Tags.Xarrray[2].Value=rd[2].ToString();
Globals.Tags.Xarrray[3].Value=rd[2].ToString();
Globals.Tags.Xarrray[4].Value=rd[2].ToString();
Well, so you want first three records which all are from the 2nd column:
i want to store Value 1 column value as: textbox1.text=hello
textboxw.text=hi1 textbox3.text=hey1
Something like this:
using (var reader = myCommand.ExecuteReader()) {
if (reader.Read())
textbox1.Text = Convert.ToString(reader.GetValue(1)); // hello
if (reader.Read())
textbox2.Text = Convert.ToString(reader.GetValue(1)); // hi1
if (reader.Read())
textbox3.Text = Convert.ToString(reader.GetValue(1)); // hey1
}
Just three conseq. reads, no while loop
To get:
hello hi1 hey1
just ignore the other columns (or don't select them if you don't need them) and only output Value1. Don't put a line break in if you really want to keep it on the same line.
You can read your input line by line, fill some structures with the data and then extract what you want using linq.
You can define a structure like:
class Data
{
public string Id;
public string Value1;
public string Value2;
public string Value3;
}
Then read all your data.
var allData = new List<Data>();
while(dr.Read())
{
var d = new Data { Id = dr.GetString(0), Value1 = dr.GetString(1), Value2 = dr.GetString(2), Value = dr.GetString(3) };
allData.Add(d);
}
var result = allData.Select(x => x.Value1);
Result is an IEnumerable< string > which contains your values. You can then do whatever you want with the values.
I'm wondering how can I use only a single select mysql statment for getting multiple values from different columns and those values to be added into a array of strings.
For example:
string[] Person = new string[3];
"Select Name,Nickname,Age From TableName";
Person[0] = Name
Person[1] = Nickname
Person[2] = Age
How can I do that?
What have I tried:
string[] Persons = new string[3];
command.CommandText = "Select Name From TableName";
MySqlDataReader myReader;
myReader = commmand.ExecuteReader();
int i = 0;
while (myReader.Read())
{
Persons[i] = myReader.GetString(0);
i++;
}
I know how to get only for 1 column.
Replace the while loop with:
if (myReader.Read())
{
Persons[0] = myReader.GetString(0);
Persons[1] = myReader.GetString(1);
Persons[2] = myReader.GetString(2);
}
myReader.Close();
This only reads one row of data. If you need to read more rows, use a loop again. See Retrieving Data Using a DataReader.