c# winform display database data from combobox selection - c#

I have a check button that will fetch the month and year in combo box:
private void cmdSend_Click(object sender, System.EventArgs e)
{
List<string>[] list;
list = dbConnect.Select(month_list.SelectedItem.ToString(), year_list.SelectedItem.ToString());
printer_info.Rows.Clear();
for (int i = 0; i < list[0].Count; i++)
{
int number = printer_info.Rows.Add();
printer_info.Rows[number].Cells[0].Value = list[0][i];
printer_info.Rows[number].Cells[1].Value = list[1][i];
printer_info.Rows[number].Cells[2].Value = list[2][i];
printer_info.Rows[number].Cells[3].Value = list[3][i];
}
}
The check button then pass the month and year to the select statement function:
public List<string>[] Select(string month,string year)
{
string query = "SELECT * FROM page_counter WHERE month = '#month' AND year = #year;";
//Create a list to store the result
List<string>[] list = new List<string>[4];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
list[3] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.Parameters.Add("#month",MySqlDbType.VarChar);
cmd.Parameters.Add("#year", MySqlDbType.Year);
cmd.Parameters["#month"].Value = month;
cmd.Parameters["#year"].Value = year;
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["id"].ToString() + "");
list[1].Add(dataReader["month"].ToString() + "");
list[2].Add(dataReader["year"].ToString() + "");
list[3].Add(dataReader["page_count"].ToString() + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
the data will then display on the gridview where all column are specified by default in page designer:
When I run the code, it doesnt have any error, but theres no value display on the gridview. Is there any mistake I make? Im newbie in c# winform,please advise.

I think you have two mistakes.First you should remove the single-quotes from query string:
string query = "SELECT * FROM page_counter WHERE month = #month AND year = #year;"
Because when you use single-quotes your parameter names treated as actual value.Secondly, I would highly recommend you to use a class for your item instead of a List<string>[].The class would look like this:
public class Data
{
public int Id { get; set; }
public string Month { get; set; }
public string Year { get; set; }
public int PageCount { get; set; }
}
Then create a List<Data> and populate it like this:
var dataList = new List<Data>();
while (dataReader.Read())
{
var item = new Data();
item.Id = Convert.Toınt32(dataReader["id"]);
item.Month = dataReader["month"].ToString();
item.Year = dataReader["year"].ToString();
item.PageCount = Convert.ToInt32(dataReader["page_count"]);
dataList.Add(item);
}
return dataList;
Then ofcourse change the returning type of your method:
public List<Data> Select(string month,string year)
Then all you need to do is set the DataSource property:
var list = dbConnect.Select(month_list.SelectedItem, year_list.SelectedItem);
printer_info.DataSource = list;

Related

How to calculate a column from Listview columns and add it to that Listview?

I want to retrieve the following Table from SQL to display in Listview
Admission ID, Room No, Admit Date, Discharge Date, Daily Charges,
1 001 2018-06-22 2018-06-29 3000
2 002 2018-06-23 2018-06-25 2500
I want to add two further columns Days and Total Charges.
The Days columns should show the days between the admit and discharge dates and total charges should be the Multiplication of Days and daily charges.
The desire Listview is:
Room ID, Room No, Admit, Discharge, Daily charges, Days, Total
1 001 2018-06-22 2018-06-29 3000 8 24000
2 002 2018-06-23 2018-06-25 2500 4 10000
Grand Total: 34000
Here is my code
listView1.GridLines = false;
listView1.View = View.Details;
listView1.FullRowSelect = true;
//Add Column Header
listView4.Columns.Add("Room ID", 80);
listView4.Columns.Add("Room No", 80);
listView4.Columns.Add("Admit Date", 90);
listView4.Columns.Add("Discharged Date", 90);
listView4.Columns.Add("Daily Charges", 90);
listView4.Columns.Add("Stayed Days", 80);
listView4.Columns.Add("Total Charges", 80);
string sql = " SELECT dbo.admission.admission_id, dbo.Room.Room_No, dbo.admission.in_date, dbo.admission.out_date, dbo.Room.daily_charges FROM dbo.admission INNER JOIN dbo.Room ON dbo.admission.Room_id = dbo.Room.Room_id WHERE (P_id = '" + textBox1.Text + "')";
SqlConnection cnn = new SqlConnection(cs);
cnn.Open();
SqlCommand cmd = new SqlCommand(sql, cnn);
SqlDataReader Reader = cmd.ExecuteReader();
listView4.Items.Clear();
while (Reader.Read())
{
ListViewItem lv1 = new ListViewItem(Reader.GetInt32(0).ToString());
lv1.SubItems.Add(Reader.GetString(1).ToString());
lv1.SubItems.Add(Reader.GetDateTime(2).ToString());
lv1.SubItems.Add(Reader.GetDateTime(3).ToString());
lv1.SubItems.Add(Reader.GetDecimal(4).ToString());
DateTime sDate, eDate;
Decimal daily = 0;
for (int i = 0; i < listView4.Items.Count; i++)
{
ListViewItem item = listView4.SelectedItems[i];
//fill the text boxes
sDate = DateTime.Parse(listView4.Items[i].SubItems[3].Text);
eDate = DateTime.Parse(listView4.Items[i].SubItems[4].Text);
String diff2 = (eDate - sDate).TotalDays.ToString();
daily = decimal.Parse(listView4.Items[i].SubItems[6].Text);
string[] row = { diff2,daily.ToString() };
}
listView4.Items.Add(lv1);
}
Reader.Close();
cnn.Close();
decimal totalDoctorCharges = 0;
for (int i = 0; i < listView4.Items.Count; i++)
{
totalDoctorCharges += decimal.Parse(listView4.Items[i].SubItems[6].Text);
}
textBox3.Text = totalDoctorCharges.ToString();
Thanks in advance!
I created a class to store the values form the database and provided the calculated values. Then a DataAccess class to separate the database work from the user interface
public class HospitalAdmission
{
//The custom constructor sets all the properties including the calculated valuew.
public HospitalAdmission(int id, string roomNum, DateTime dateIn, DateTime dateOut, decimal dayRate)
{
ID = id;
RoomNum = roomNum;
In = dateIn;
Out = dateOut;
DayRate = dayRate;
LengthOfStay = Out.Subtract(In).Days;
TotalFee = DayRate * LengthOfStay;
}
public int ID { get; set; }
public string RoomNum { get; set; }
public DateTime In { get; set; }
public DateTime Out { get; set; }
public decimal DayRate { get; set; }
public int LengthOfStay { get; set; }
public decimal TotalFee;
}
public class DataAccess
{
public List<HospitalAdmission> lstHosAdmin = new List<HospitalAdmission>();
public void GetData()
{
//I am not very sure of your select statement. Please check it in SSMS
//P_id will have to be a column in one of your tables, qualify it with the table name as you have done for the other fields
string sql = " SELECT dbo.admission.admission_id, dbo.Room.Room_No, dbo.admission.in_date, dbo.admission.out_date, dbo.Room.daily_charges FROM dbo.admission INNER JOIN dbo.Room ON dbo.admission.Room_id = dbo.Room.Room_id WHERE P_id = #pid;";
//using ensures that you objects are closed and disposed even if there is an error
using (SqlConnection cnn = new SqlConnection("Your connection string"))
{
using (SqlCommand cmd = new SqlCommand(sql, cnn))
{
//Always use parameters to prevent Sql Injection
//I assumed P_id was a VarChar because it was surronded by quotes check the db for correct datatype
cmd.Parameters.Add("#pid", SqlDbType.VarChar).Value = textBox1.Text;
cnn.Open();
using (SqlDataReader Reader = cmd.ExecuteReader())
{
while (Reader.Read())
{
//calls the custom constructor passing in the values from the database
HospitalAdmission ha = new HospitalAdmission(Reader.GetInt32(0),Reader.GetString(1),Reader.GetDateTime(2), Reader.GetDateTime(3),Reader.GetDecimal(4));
lstHosAdmin.Add(ha);
}
}
}
}
}
}
public partial class Form1 : Form
{
private List<HospitalAdmission> lstHA
private void Form1_Load(object sender, EventArgs e)
{
DataAccess da = new DataAccess();
da.GetData();
lstHA = da.lstHosAdmin;
FillListView();
}
private void FillListView()
{
listView4.GridLines = false;
listView4.View = View.Details;
listView4.FullRowSelect = true;
//Add Column Header
listView4.Columns.Add("Room ID", 80);
listView4.Columns.Add("Room No", 80);
listView4.Columns.Add("Admit Date", 90);
listView4.Columns.Add("Discharged Date", 90);
listView4.Columns.Add("Daily Charges", 90);
listView4.Columns.Add("Stayed Days", 80);
listView4.Columns.Add("Total Charges", 80);
listView4.BeginUpdate();
foreach (HospitalAdmission ha in lstHA)
{
ListViewItem lv1 = new ListViewItem(ha.ID.ToString());
lv1.SubItems.Add(ha.RoomNum.ToString());
lv1.SubItems.Add(ha.In.ToString());
lv1.SubItems.Add(ha.Out.ToString());
lv1.SubItems.Add(ha.DayRate.ToString());
lv1.SubItems.Add(ha.LengthOfStay.ToString());
lv1.SubItems.Add(ha.TotalFee.ToString());
listView4.items.Add(lv1);
}
listView4.EndUpdate();
}
}
}

How to get values in two indexes of a string list and assign them to two string variables C#

I'm implementing a method to return the result set that generated from the query and assign it to a string list. I have set to assign the id (id is a primary key) and name of selected db table line to index 0 and 1 in the string list. The code of that as follows,
public List<string>[] getTrafficLevel()
{
string query = "select * from traffictimeinfo where startTime<time(now()) and endTime>time(now());";
List<string>[] list = new List<string>[2];
list[0] = new List<string>();
list[1] = new List<string>();
if (this.openConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
list[0].Add(dataReader["timeslotid"] + "");
list[1].Add(dataReader["timeslotname"] + "");
}
dataReader.Close();
this.closeConnection();
return list;
}
else
{
return list;
}
}
What I want to know is how can i assign this values in two indexes into two string variables.
the method that i tried is as follows, is there anyone who knows how to implement this.. Thanks in advance..
public void predictLevel(List<String>resList)
{
string trafficTime, trafficLevel;
List<string>[]ansList = getTrafficLevel();
ansList[0] = # want to assign the string value into trafficTime string variable
ansList[1].ToString = # want to assign the string value into trafficLevel string variable
}
Have you considered using List of Tuples instead?
public List<Tuple<string,string>> getTrafficLevel()
{
string query = "select * from traffictimeinfo where startTime<time(now()) and endTime>time(now());";
List<Tuple<string,string>> list = new List<Tuple<string,string>>();
if (this.openConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
list.Add(new Tuple<string,string>(dataReader["timeslotid"] + "", dataReader["timeslotname"] + ""));
}
dataReader.Close();
this.closeConnection();
return list;
}
else
{
return list;
}
}
And your predictLevel method would be -
public void predictLevel(List<String>resList)
{
string trafficTime, trafficLevel;
List<Tuple<string,string>> ansList = getTrafficLevel();
trafficTime = ansList[0].Item1;
trafficLevel = ansList[0].Item2;
}

Insert new row to SQL DB using Stored Procedure and two parameters

I am trying to insert a new row to SQL DB using a stored procedure that takes two parameters. I am using an asp.net gridview and checkboxes in the first column so that you can select the row. For each row that is selected, it will insert the new row which supplies the ProjectID. The CorpID is provided with the query string. I commented out some of the lines in my code because it is giving me errors and I am not sure how to do the rest. I am following a video on YouTube to get this done. In the video, they are deleting rows but I am attempting to insert rows. If anyone wants the link to the video it is this. Here is my code from the DataAccessLayer
public void AssociateCorpToProj(ProjectData pd)
{
using(SqlConnection cn = new SqlConnection(_dbConnection))
{
using(SqlCommand cm = new SqlCommand("InsertProjectEntity", cn))
{
cm.CommandType = CommandType.StoredProcedure;
cn.Open();
cm.Parameters.AddWithValue("#ProjectID", pd.ProjectID);
cm.Parameters.AddWithValue("#CorpID", pd.CorpID);
cm.ExecuteNonQuery();
cn.Close();
}
}
}
Here is my code for my code behind that calls the method from the DataAccessLayer
protected void btnAssociateProjects_Click(object sender, EventArgs e)
{
List < object > lstCorpProjAssoc = new List < object> ();
foreach(GridViewRow gvRow in gvProjects.Rows)
{
if (((CheckBox) gvRow.FindControl("cbInsert")).Checked)
{
string cID = ((Label) gvRow.FindControl("lblProjectID")).Text;
lstCorpProjAssoc.Add(cID);
}
}
foreach(ProjectData str in lstCorpProjAssoc)
{
DALSectionAccessData ap = new DALSectionAccessData(connString);
ProjectData pd = new ProjectData();
ap.AssociateCorpToProj(str);
}
}
In case anyone thinks they need the code for the stored procedure, here it is.
INSERT INTO [dbo].[ProjectEntity]
([ProjectID],[CorpID])
VALUES
(#ProjectID, #CorpID)
Also, the list class that I am using
public class ProjectData
{
public string CompanyName { get; set; }
public int ProjectID { get; set; }
public int CorpID { get; set; }
}
Let me know if you need more information to answer the question. Any help is much appreciated.
Try running this example and step through the code this will help you understand List<object> vs List<string> vs List<Class>
var listAllData = new List<object>();
for (var cnt = 0; cnt< 10; cnt++)
{
var lstProjectData = new List<object>() //you need to change yours to be new List<ProjectData>
{
string.Empty, //CompanyName
0, //ProjectID
0 //CorpId
};
lstProjectData [0] = string.Format("CompanyName {0}", cnt);
lstProjectData [1] = cnt+ 1;
lstProjectData [2] = cnt+ 2;
listAllData.Add(lstProjectData );
//from your List<ProjectData> you should be able to get at the variable
//as follows someVariable.CompanyName = ,
//someVariable.ProjectId = ,
//and someVariable = CorpId
}
For the code in the DataAccessLayer:
public void AssociateCorpToProj(int pd, int cd)
{
using(SqlConnection cn = new SqlConnection(_dbConnection))
{
using(SqlCommand cm = new SqlCommand("InsertProjectEntity", cn))
{
cm.CommandType = CommandType.StoredProcedure;
cn.Open();
cm.Parameters.AddWithValue("#ProjectID", pd);
cm.Parameters.AddWithValue("#CorpID", cd);
cm.ExecuteNonQuery();
cn.Close();
}
}
}
For the code for the code behind that calls the method from the DataAccessLayer:
protected void btnAssociateProjects_Click(object sender, EventArgs e)
{
List < int > lstCorpProjAssoc = new List < int > ();
foreach(GridViewRow gvRow in gvProjects.Rows)
{
if (((CheckBox) gvRow.FindControl("cbInsert")).Checked)
{
int cID = Convert.ToInt32(((Label) gvRow.FindControl("lblProjectID")).Text);
lstCorpProjAssoc.Add(cID);
}
}
foreach(int pstr in lstCorpProjAssoc)
{
DALSectionAccessData ap = new DALSectionAccessData(connString);
ap.AssociateCorpToProj(pstr, _cID);
}
}
Not using the list class. I tested this out and it worked. The parameters are both int so it worked perfectly.

Comparing dataSet values

Im using this code to do display images to edit:
protected void Repeater_Outer_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
Repeater Inner = (Repeater)item.FindControl("image_Repeater");
HiddenField Inner_Id = (HiddenField)item.FindControl("HiddenField_Id");
MySqlConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["dbcnx"].ToString());
MySqlCommand cmdNew = new MySqlCommand();
cmdNew.Connection = conn;
cmdNew.Parameters.AddWithValue("#id", Inner_Id.Value);
cmdNew.CommandText = "SELECT * FROM images WHERE FK_album = #id";
conn.Open();
Inner.DataSource = cmdNew.ExecuteReader();
Inner.DataBind();
Label Label_Amount = (Label)item.FindControl("Label_Amount");
Label_Amount.Text = Convert.ToString(Inner.Items.Count);
conn.Close();
}
}
My problem is that each time the repeater runs it connects to the database which makes the page take really long to load (like 10 seconds)
So i want to populate a dataset or a generic List to databind instead. I've tried this:
protected static List<string> dataSetImages(){
MySqlConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["dbcnx"].ToString());
string sql = "select * from images";
MySqlCommand cmd = new MySqlCommand( sql, conn);
conn.Open();
MySqlDataAdapter sqlDataAdapter = new MySqlDataAdapter(cmd);
DataSet dataSet = new DataSet();
sqlDataAdapter.Fill(dataSet);
conn.Close();
List<string> imageList = new List<string>();
for (int i = 0; i <= dataSet.Tables[0].Rows.Count - 1; i++)
{
string id = dataSet.Tables[0].Rows[i].ItemArray[0].ToString();
string img_name = dataSet.Tables[0].Rows[i].ItemArray[1].ToString();
string img_alt = dataSet.Tables[0].Rows[i].ItemArray[2].ToString();
string FK_album = dataSet.Tables[0].Rows[i].ItemArray[3].ToString();
imageList.Add(id);
imageList.Add(img_name);
imageList.Add(img_alt);
imageList.Add(FK_album);
}
return imageList;
}
How can i use this and compare FK_album to Inner_Id.Value?
If you are insistent on using the RowFilter approach, then this is what you are looking for.
string expression = String.Format("FK_album = {0}", Inner_Id.Value);
DataRow[] filteredRows = imageList.Tables[0].Select(expression);
Here is an article on DataView RowFilter Syntax.
better if you can class like below
public class ImageDto
{
public string Id { get; set; }
public string Name { get; set; }
public string Alt { get; set; }
public string FK_album { get; set; }
}
then
protected static List<ImageDto> dataSetImages(){
List<ImageDto> imageList = new List<ImageDto>();
// add items
return imageList;
}
then you can call above method and get list of ImageDto
List<ImageDto> images = dataSetImages();
in your Repeater_Outer_ItemDataBound method you can do as below
Inner.DataSource = images.Where(i=>i.FK_album == Inner_Id.Value).ToList();

getting a select statement column info from combobox

Hopefully i don't sound confusing but i am not sure if what i am trying to get at is possible.
I have a select statement to get name, id, guid. I am setting the display to name and the value to Id for each combobox. Is there a way that i could also assign the guid to the combo box so that i could use it in my winforms app?
here is what i have for select statement:
private void secondChild_drp_SelectedIndexChanged(object sender, EventArgs e)
{
string secondChildId = secondChild_drp.SelectedValue.ToString();
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
using (SqlDataAdapter sda = new SqlDataAdapter("SELECT ... WHERE em.ChildID = (" + secondChildId + ")", conString))
{
DataTable dt = new DataTable();
sda.Fill(dt);
thirdChild_drp.ValueMember = "ID";
thirdChild_drp.DisplayMember = "DisplayName";
thirdChild_drp.DataSource = dt;
}
}
cmd.CommandText="StoreProcName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ChildID", secondChildId);
cmd.Connection = con2;
con2.Open();
reader = cmd.ExecuteReader();
var guid = reader.ToString();
reader.Close();
con2.Close();
}
right now when i run this it tells me reader = cmd.ExecuteReader(); has Procedure or function StoreProcName has too many arguments specified.
i just want to get the guid associated with the id i passed in.
You can get the guid from your datatable as follows where yourselectedid is the combobox selecteditem id.
var results = from row in dt.AsEnumerable()
where row.Field<int>("ID") == yourselectedid
select row;
now from results you can get all the desired columns you want
Basically the same answer as I already posted here:
You could define a simple object which you are filling from your data base query:
public class Item
{
public int ID { get; set; }
public string DisplayName { get; set; }
public Guid Guid{ get; set; }
}
Your implementation could look something like this (some mockup data):
listBox1.DataSource = items;
listBox1.DisplayMember = "DisplayName";
listBox1.ValueMember = "ID";
Then based on the value you selected, you can query through your items and get the item:
var key = (int)listBox1.SelectedValue;
foreach (var existingItem in items)
{
if (existingItem.Key == key)
{
//woohoo got it!
Debug.Print(existingItem.Guid.ToString())
}
}
you can put both of the value in the value member, separated by whichever character for separator like : "12;0000-000-0000" then separate again the Value Menber with a String.Split.

Categories