multiple input from users to save in database in one column - c#

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?

Related

There is no Row at Position -1

I am receiving this sql error there is no row at position - 1.
This is what I have done.
void showData(int index)
{
Connection con = new OrderManager.Connection();
SqlDataAdapter sda = new SqlDataAdapter("Select * from [MasterDatabase].[dbo].[Neworder] Where OrderID = '" + TxtBox_OrderID.Text + "'", con.ActiveCon());
dt = new DataTable();
sda.Fill(dt);
TxtBox_OrderID.Text = dt.Rows[index][0].ToString();
ClearTextBoxes();
dataGridView1.Rows.Clear();
foreach (DataRow item in dt.Rows)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = item["OrderID"].ToString();
dataGridView1.Rows[n].Cells[1].Value = item["Date"].ToString();
dataGridView1.Rows[n].Cells[2].Value = item["Customer_Name"].ToString();
dataGridView1.Rows[n].Cells[3].Value = item["ProductID"].ToString();
dataGridView1.Rows[n].Cells[4].Value = item["Product_Name"].ToString();
dataGridView1.Rows[n].Cells[5].Value = item["Product_Color"].ToString();
dataGridView1.Rows[n].Cells[6].Value = item["Product_PCs"].ToString();
dataGridView1.Rows[n].Cells[7].Value = item["Product_Cutting"].ToString();
dataGridView1.Rows[n].Cells[8].Value = item["Product_TotalYards"].ToString();
}
label12.Text = "Row Count: " + dt.Rows.Count.ToString();
}
I want to display only those records while navigating whose OrderID is equals to the order ID in the database.
I think your error happens on this line
TxtBox_OrderID.Text = dt.Rows[index][0].ToString();
this is not an SQL error but a simple index out of the bounds of the array.
For some reasons, when you try to use a row that is not included in the Rows collection of the datatable you get this error message instead of the less ambiguous IndexOutOfRangeException. This message comes if you pass some value for the index variable that is less than zero or bigger than the number of rows in the datatable dt.
You don't have any check on the number of rows returned by the query and thus is possible that your query doesn't return any record or simple the value of index is -1
void showData(int index)
{
Connection con = new OrderManager.Connection();
SqlDataAdapter sda = new SqlDataAdapter(".......", con.ActiveCon());
dt = new DataTable();
sda.Fill(dt);
// Protect the access to the rows collection of the table...
if(index < dt.RowsCount && index >= 0)
{
TxtBox_OrderID.Text = dt.Rows[index][0].ToString();
// the code that fills the datagrid
}
else
{
// Message for your user about a record not found
}
}
As a side note, please follow ASAP the advice given to parameterize your query. You will avoid Sql Injection and parsin problems

Insert multiple data into two tables and need to insert the last inserted id into another table

I have a form which use two tables to insert the data.
Some column in the form would be like:
scholarship name, course, year
Two tables that are involved are:
scholarshipDetail , scholarshipCourse.
scholarshipDetail table has scholarshipName and year
scholarshipCourse table has scholarshipID, course
scholarshipDetail:
schid schName year
-----------------------------
1 star 2015
2 moon 2016
scholarshipCourse:
schID course
------------------
1 maths
1 english
2 maths
Assuming that the new user wants to add new scholarship which means the id will 3 and it insert into two tables. How do I that? (MANAGED TO INSERT ALR)
NEW ERROR:
EDITED
public DataTable test(string name, string course)
{
string insertsql = "INSERT INTO Table1(schName) OUTPUT INSERTED.addID values (#schName)";
SqlCommand cmd = new SqlCommand(insertsql,conn);
cmd.Parameters.AddWithValue("#schName", name);
conn.Open();
int i = cmd.ExecuteNonQuery();
var table1Id = (int)cmd.ExecuteScalar();
string insertsql1 = "INSERT INTO Table2(ScholarshipID, DiplomaCourse) VALUES (#id, #course)";
SqlCommand cmd2 = new SqlCommand(insertsql1, conn);
cmd2.Parameters.AddWithValue("#id", table1Id);
cmd2.Parameters.AddWithValue("#course", course);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.SelectCommand = cmd2;
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
The output in my table is
Table1
schID schname
-------------------
1 jj
2 jj
Table2
TableID schID Course
------------------------------
1 2 Maths
the data is being inserted twice in Table1. why is that so? (SOLVED)
Edited:
Now the problem is, there will be checkboxes which allow the user to choose which course is applicable for the scholarship.
When the user click all checkbox, only the last checkbox will insert into database.
In my codebehind(cs):
protected void Button1_Click(object sender, EventArgs e)
{
// addScholarship[] test = new addScholarship[1];
string course = "";
string Name = schName.Text;
if (DIT.Checked )
{
course = "DIT";
}
if (DFI.Checked)
{
course = "DFI";
}
addScholarship[] insertName = new addScholarship[1];
addScholarship insertedName = new addScholarship(Name,course);
scholarshipBLL obj = new scholarshipBLL();
DataTable dt = obj.test(Name, course);
}
For the latest problem you posted.
You are calling obj.test method only once after all the if blocks.
So the "course" variable will have value from the latest if block where the condition is true.
You need to call DataTable dt = obj.test(Name, course); method in every if block. That means if checkbox is checked you call insert row. If not checked then you don't insert the row.
Following is the code you should put in your button_click.
string course = "";
string Name = schName.Text;
scholarshipBLL obj = new scholarshipBLL();
List<addScholarship> addScholarshipList= new List<addScholarship>();
addScholarship scholarship;
if (DIT.Checked )
{
scholarship = new addScholarship(Name,course);
addScholarshipList.Add(insertedName);
course = "DIT";
DataTable dt = obj.test(Name, course);
}
if (DFI.Checked)
{
scholarship = new addScholarship(Name,course);
addScholarshipList.Add(insertedName);
course = "DFI";
DataTable dt = obj.test(Name, course);
}
You are executing the command twice.
int i = cmd.ExecuteNonQuery();
var table1Id = (int)cmd.ExecuteScalar();
You need to execute only one. I think removing cmd.ExecuteNoteQuery would solve your issue.
BEGIN;
INSERT INTO scholarshipDetail(schid,schName,year) VALUES(3,'sun',2017);
INSERT INTO scholarshipCourse(schID,course) VALUES(LAST_INSERT_ID(),'science');
COMMIT;

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,

Getting "Index was outside of bounds of the Array"

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();

Select some of records from database and display in data grid through c# with sqlite database

I have a sample database like below, and I want to display only the red colored records in the datagrid. I have a condition for how to make those two cells red.
Sample Database
For example, I want to display records whose is value less than 10 in the book number column.
I used code like below for making them red.
Code
private void UpdateDataGridViewColor()
{
if (calledMethod == 2)
{
for (int i = 0; i < dataGridView1.RowCount; i++)
{
int j = 6;
DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
CellStyle.ForeColor = Color.Red;
if (isLate(dataGridView1[j, i].Value.ToString()))
{
dataGridView1[j, i].Style = CellStyle;
}
}
}
}
I used code something like the following.
Code
private void issueDetails()
{
calledMethod = 2;
string connectionPath = #"Data Source=Data\libraryData.dat;Version=3;New=False;Compress=True";
using (SQLiteConnection connection = new SQLiteConnection(connectionPath))
{
SQLiteCommand command = connection.CreateCommand();
connection.Open();
string query = "SELECT bookno as 'Book No.',studentId as 'Student ID', title as 'Title', author as 'Author', description as 'Description', issuedDate as 'Issued Date', dueDate as 'Due Date' FROM issuedBooks";
command.CommandText = query;
command.ExecuteNonQuery();
SQLiteDataAdapter da = new SQLiteDataAdapter(command);
DataSet ds = new DataSet();
da.Fill(ds, "issuedBooks");
int c = ds.Tables["issuedBooks"].Rows.Count;
dataGridView1.DataSource = ds.Tables["issuedBooks"];
dataGridView1.Sort(dataGridView1.Columns["Student ID"], ListSortDirection.Ascending);
dataGridView1.ReadOnly = true;
connection.Close();
this.Totals.Text = "Total Issued Books : " + Convert.ToString(c);
}
}
Have you tried,
foreach(DataGridView row in dataGridView1.Rows)
{
//check whether bookno. column in 'row' is less than 10
//and do something
}
I just read your comment that you want query from the database directly before displaying in datagridview, is that what you want?
For SQLite databases, check out this link, you can use standard SQL select statements to get the records based on your condition. Example SELECT * From <table> Where bookNum > 10
That should give you all the records with bookNum greater than 10.
First create your connection,
SQLiteConnection connection = new SQLiteConnection(connectionPath)
Then the dataadapter
SQLiteDataAdapter da = new SQLiteDataAdapter(query, connection);
Do your table mappings if any.
And then call da.Fill(ds, "issuedBooks");
I also noticed you were using As in your sql query for the column names. You can actually use tablemappings to map your database column name to the datatable column name. See this link.
Answer
public void onlyDueReport()
{
List<int> array = new List<int>();
string connectionPath = #"Data Source=Data\libraryData.dat;Version=3;New=False;Compress=True";
using (SQLiteConnection connection = new SQLiteConnection(connectionPath))
{
SQLiteCommand command = connection.CreateCommand();
connection.Open();
string query = "SELECT bookno as 'Book No.',studentId as 'Student ID', title as 'Title', author as 'Author', description as 'Description', issuedDate as 'Issued Date', dueDate as 'Due Date' FROM issuedBooks";
command.CommandText = query;
command.ExecuteNonQuery();
SQLiteDataAdapter da = new SQLiteDataAdapter(command);
DataSet ds = new DataSet();
da.Fill(ds, "issuedBooks");
int c = ds.Tables["issuedBooks"].Rows.Count;
if (c > 0)
{
for (int row = c; row > 0; row--)
{
string date = (string)(ds.Tables["issuedBooks"].Rows[c - row]["Due Date"]);
if (isLate(date))
{
int a = Convert.ToInt32(ds.Tables["issuedBooks"].Rows[c - row]["Book No."]);
array.Add(a);
}
}
}
query = "SELECT bookno as 'Book No.',studentId as 'Student ID', title as 'Title', author as 'Author', description as 'Description', issuedDate as 'Issued Date', dueDate as 'Due Date' FROM issuedBooks WHERE bookno IN (";
int[] cool = array.ToArray();
int cou = 0;
foreach (int a in cool)
{
query += a;
if (cou < cool.Length - 1) { query += ','; }
cou++;
}
query += ")";
Console.WriteLine(query);
command.CommandText = query;
command.ExecuteNonQuery();
DataSet ds1 = new DataSet();
da.Fill(ds1, "issuedBooks");
dataGridView1.DataSource = ds1.Tables["issuedBooks"];
this.Totals.Text = "";
Report_Viewer.StatusPText = " Total Pending Books : " + ds1.Tables["issuedBooks"].Rows.Count;
}
}

Categories