Getting "Index was outside of bounds of the Array" - c#

I am getting the error, and not sure how to fix it. When I change the SQL command to another query, it seems to work (with the same amount of data, 10 rows). Ideas? Note: I am aware I should be using parameters in my SQL command, i am just testing.
SqlCommand getLabsCommand = new SqlCommand("SELECT labGrade FROM labStudent WHERE studentID = '"+Label1.Text+"' ");
getLabsCommand.Connection = conn;
ArrayList alMakers = new ArrayList();
conn.Open();
SqlDataReader dr = getLabsCommand.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
//alMakers.Add(dr.GetString(1));
alMakers.Add(dr.GetInt32(1));
}
}
string[] labsList = (string[])alMakers.ToArray(typeof(string));
for(int i = 0; i < alMakers.Count; i++)
{
TextBox labs = new TextBox();
labs.ID = "lab" + i;
form1.Controls.Add(labs);
labs.Text = labsList.GetValue(i).ToString();
}
dr.Close();
conn.Close();
}
The function above should be putting these values in each textbox.
25
25
25
25
20
22
25
10
15
16

You are only selecting one column (SELECT labGrade FROM...); indexing is 0-based, so only GetInt32(0) is defined. GetInt32(1) refers to the second column (the first column is index 0, second column is index 1, etc). You probably want:
alMakers.Add(dr.GetInt32(0));
This type of thing is where tools like dapper shine, btw:
var alMakers = conn.Query<int>(
"SELECT labGrade FROM labStudent WHERE studentID = #id",
new { id = Label1.Text }).AsList();

Related

MySQL get value

Since yesterday I am trying to get this value (see image), I have tried to use "mysqlreader, executescalar and more", but I cannot get the number of lines.
What I want to do is this:
If the result is 0 it does nothing, if equal to 1 it must show an image, if greater than 1 it must show another image
ex code 1
private void patient()
{
if (OpenEventMissionData.Rows.Count != 0)
{
foreach (DataGridViewRow row in OpenEventMissionData.Rows)
{
string idevent = row.Cells[1].Value.ToString();
string sql = "SELECT COUNT(*) FROM patient INNER JOIN event WHERE patient.ID_EVENT = " + "'" + idevent + "'" + "AND evento.EVENT_OPEN = 1;";
MySqlConnection connection = new MySqlConnection();
connection.ConnectionString = ConfigurationManager.ConnectionStrings["dbx"].ConnectionString;
MySqlCommand cmd = new MySqlCommand(sql, connection);
connection.Open();
MySqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
DataGridViewButtonColumn patient = new DataGridViewButtonColumn();
OpenEventMissionData.Columns.Add(new PatientColumn());
}
}
}
}
I tried adding the code that told me #oldDog, but the result is always 6
ex code 3
NEW EDIT:
In fact 6 lines appear.
phpmyadmin
Your problem here is you are using HasRows. Since you are doing SELECT COUNT(*) you will always have one row which will contain the count, even if the count is zero. Instead you could use:
if (Convert.ToInt32(reader[0]) > 0)

how to make the datagridview load faster with Multiple Row query - c# SQL

The code:
private void suppPopulate()
{
byCode.Text = "Supplier Code";
byDesc.Text = "Supplier";
DGViewListItems.Columns.Add("custcode", "Customer Code");
DGViewListItems.Columns.Add("customer", "Customer");
DGViewListItems.Columns[0].ReadOnly = true;
DGViewListItems.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
DGViewListItems.Columns[1].ReadOnly = true;
DGViewListItems.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
using (SqlConnection con = db.Connect())
{
SqlDataReader rd;
SqlCommand cmd = new SqlCommand("SELECT DISTINCT custcode, custname FROM Customers WHERE type = 'V';", db.Connect());
rd = cmd.ExecuteReader();
int i = 0;
if (rd.HasRows)
{
while (rd.Read())
{
DGViewListItems.Rows.Add();
DGViewListItems.Rows[i].Cells["custcode"].Value = rd["custcode"].ToString().Trim();
DGViewListItems.Rows[i].Cells["customer"].Value = rd["custname"].ToString().Trim();
}
}
cmd.Connection.Close();
}
}
The SSMS output:
The output form loads slowly, the rows for the query are over 1000 so I think the cause of the slow load is the number of returned rows? If yes, how do make the load of the datagridview faster?
NOTE - this answer relates to the first part of the original question regarding why only a single row of the DataGrid being populated.
Incrementing the counter "i" at the bottom of the while loop looks like it may fix the problem.
You are adding rows, but only updating the first.

C# - Retrieving data from mysql then storing into variables

I have been trying a more efficient way to get and set data from my database in mysql to a variable. I've used a for loop to shorten the code and make it easier to read, though i can't think of a way to properly set other variables. Here's my code:
Note: I use 18 different local variables. (i.g ad, mnd, psk, pck, etc..)
for (int i = 1; i <= 18; i++) {
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT price from products where productID = '" + i + "'";
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
ad = Convert.ToInt32(reader.ToString());
}
}
I am trying to retrieve the prices of 18 products from the database, but on this piece of code, I can only set one price. Any kind of help would be appreciated.
You assign all prices to 1 variable. Your code run like this
ad = 150; //sample price
ad = 240;
ad = 100;
...(18 times)
You have to use array instead of single variable.
Change your code to :
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT price from products where productID > 1 AND productID < 19" ;
MySqlDataReader reader = cmd.ExecuteReader();
int counter = 0;
while (reader.Read()) {
ad[counter++] = Convert.ToInt32(reader.ToString());
}
Okay, change your schema a bit, so you have
name | price | id
------------------------
'ad' 1.00 1
'mnd' 42.24 2
'psk' 6.66 3
'pck' 2.00 4
'etc' 9999.99 5
...
Then use Dapper like this,
using Dapper;
...
IDictionary<string, decimal> products;
using(var connection = new SqlConnection(GetConnectionString()))
{
connection.Open();
products = connection.Query("SELECT name, price FROM products;")
.ToDictionary(
row => (string)row.Name,
row => (decimal)row.Price);
}
then you can get whatever product you want like this,
var adPrice = products["ad"];
Once you have many products (a lot more than 18) you won't want to hold them all in memory at once but for now this would work well.

Update the First Row in a database C# mysql

My problem is that:
I want to Select one row from the database, The data should be arrange in expiry (the ones that are not yet expired and I don't want to limit it). The items that passed the current date must be left alone. And with all the same ITEMID lets say I00001.
Then after selecting I want to Update the first row of the database. if the quantity reaches 0 then it will go the next row to update and so on.
Here is my example
Here is the current database screenshot.
I want select the itemid where = I00001 and deduct 50.
Then it should look like this
Then I want to arrange based on the expiry as I mentioned above.
Select the first row.
Deduct the 50 from the quantity. (as I also mentioned above).
Here is my code:
for (int i = 0; i < dataGridView.Rows.Count; i++)
{
cmd = new MySqlCommand(#"SELECT * FROM inventory2 WHERE itemid = #itemid ORDER BY expiry ", sqlconnection);
cmd = new MySqlCommand(#"UPDATE inventory2 SET quantity = #quantity WHERE itemid = #itemid ORDER BY expiry)", sqlconnection);
sqlconnection.Open();
cmd.ExecuteNonQuery();
sqlconnection.Close();
}
I'm open for another suggestion in doing this. I hope you understand my problem. Thank you very much. I'm sorry I cannot send another screenshot.
Try this,
void UpdateQuantity() {
// your connection string
MySqlDataAdapter adp = new MySqlDataAdapter("Select * from table where ItemID = " + 13 + " Order BY expiry", cnn); // I have test db and I used it
DataTable dt = new DataTable();
adp.Fill(dt);
int deductNum = 50;
foreach (DataRow item in dt.Rows)
{
int value = (int)item["quantity"];
if (value >= deductNum) // if had enough stock we don't need to pass the next line
{
int result = value - deductNum;
item["quantity"] = result.ToString();
break; // so need to exit from loop
}
else
{
deductNum -= value; // else we deduct value count from deduction
item["quantity"] = 0; // quantity finished so it will be 0
}
}
MySqlCommandBuilder cmb = new MySqlCommandBuilder(adp);
adp.UpdateCommand = cmb.GetUpdateCommand();
adp.Update(dt);
dataGridView1.DataSource = dt; //to show the result
}
(You can calculate :))
Hope helps,

multiple input from users to save in database in one column

I don't know how to describe what I am looking for but i can illustrate it with diagram which I drawn.
The first below here is 'user input' which will be in gridview and it will require users to input details. the (textbox) is a textbox and the details next to it is an input example.
User Inputs:
Items Quantity Unit Price Total
(textBox)abc (textBox)2 (textBox) 100 (textBox) 200
(textBox)def (textBox)1 (textBox) 150 (textBox) 150
After save button is clicked (I didn't show the button, sorry), the details will be saved in the database such as shown below 'save in database'.
Save in Database:
ID Items Quantity UnitPrice Total
10001 Abc , def 2,1 100,150 200,150
And when the user wants to display the details, the details should show like in the below 'display results'.
Display Results:
ID:10001
Items Quantity Unit Price Total
Abc 2 100 200
def 1 150 150
I hope this explanation is understandable, I am quite poor in explaining and also in ASP.
please help me to code this out in C# or VB because I am out of option to do this.
thank you so much.
code example:
string sql = "INSERT INTO Products(Name, ProductImage, OriginalPrice, DiscountPrice, Descriptions,StockQuantity, Category) VALUES (#Name, #ProdImage, #OriPrice, #DisPrice, #Descrp, #Quantity, #Category)";
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
SqlParameter[] param = new SqlParameter[7];
param[0] = new SqlParameter("#Name", SqlDbType.VarChar,100);
param[1] = new SqlParameter("#ProdImage", SqlDbType.VarChar, 100);
param[2] = new SqlParameter("#OriPrice", SqlDbType.Float );
param[3] = new SqlParameter("#DisPrice", SqlDbType.Float );
param[4] = new SqlParameter("#Descrp", SqlDbType.VarChar,50);
param[5] = new SqlParameter("#Quantity", SqlDbType.Int);
param[6] = new SqlParameter("#Category", SqlDbType.VarChar,50);
param[0].Value = name;
param[1].Value = image;
param[2].Value = OriPrice;
param[3].Value = disPrice;
param[4].Value = description;
param[5].Value = quantity;
param[6].Value = Category;
for (int i = 0; i < param.Length; i++)
{
cmd.Parameters.Add(param[i]);
}
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
current code:
private string CreateRow(DataTable data, Int32 index, String ColumnName)
{
String[] quan = data.Rows[0][ColumnName].ToString().Split(',');
if (quan.Length >= index)
return quan[index].ToString();
else
return "";
}
protected void GridView2_SelectedIndexChanged(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection("");
string sql = "SELECT * FROM SalesOrder WHERE ID = 10010";
DataSet DataFromDataBase = new DataSet();
SqlDataAdapter adp = new SqlDataAdapter("SELECT * FROM SalesOrder WHERE ID = 10010", conn);
adp.Fill(DataFromDataBase);
DataTable TempData = new DataTable();
TempData.Columns.Add("Quantity", typeof(string));
TempData.Columns.Add("UnitPrice", typeof(string));
for (Int32 i = 0; i < 5; i++)
{
DataRow row = TempData.NewRow();
row[0] = CreateRow(DataFromDataBase, i, "Quantity");
row[1] = CreateRow(DataFromDataBase , i, "UnitPrice");
TempData.Rows.Add(row);
}
}
DataFromDataBase is a datatable in which you are getting your data from database.
At last you'll get data in your required format in TempData Datatable.
you have to bind Grisview with TempData Datatable.
I have done this work with only two columns, you can change it according to your columns. I have taken maximum 5 as your maximum number of values in one field. you can modify according to your requirement.
DataTable TempData = new DataTable();
TempData.Columns.Add("Quantity", typeof(string));
TempData.Columns.Add("UnitPrice", typeof(string));
for (Int32 i = 0; i < 5; i++)
{
DataRow row = TempData.NewRow();
row[0] = CreateRow(DataFromDataBase, i, "Quantity");
row[1] = CreateRow(DataFromDataBase, i, "UnitPrice");
TempData.Rows.Add(row);
}
private string CreateRow(DataTable data, Int32 index, String ColumnName)
{
String[] quan = data.Rows[0][ColumnName].ToString().Split(',');
if (quan.Length >= index)
return quan[index].ToString();
else
return "";
}
If you are getting data in DataSet from database. you can pass parameter to CreateRow function as below
CreateRow( DataFromDataBase.Tables[0], i, "UnitPrice");
EDIT like this you have to get data in dataset or datatable (your choice)
DataSet DataFromDataBase = new DataSet();
SqlDataAdapter adp = new SqlDataAdapter("select * from tbdep;select * from tbemployee", ConfigurationManager.ConnectionStrings["cn"].ConnectionString);
adp.Fill(DataFromDataBase);
the way you are saving the values is really unrealistic and denormalized.
you should save the values like:
ID Items Quantity UnitPrice Total
10001 Abc 2 100 200
10001 def 1 150 150
and you can use following query in sql:
select * from table where ID = 10001
It will return you two rows in datatable or dataset(whatever you use). you can easily bind it with any control like GridView, Repeater and Datalist.
By this way you can easily reduce you code to display data in your required format.
may it'll help you.
What you are trying to achieve is possible in code, but would require custom concatenation and splitting when reading and writing to storage.
However, I would suggest that you normalize your data and create 2 tables:
IdHeader
HeaderId
CreatedOn
UserName
etc
IdDetail
HeaderId
Item
Quantity
UnitPrice
Total
etc
If you want them under the same ID why not add another column, say OrderId?

Categories