I have a datagridview that holds the bio_id and email. I am iterating through the datagridview to get the time records of the employee based on the bio_id and dates. If I create a MySql syntax in the MySql itself, it gets the right value but when I use the MySqlDataReader, it gives me a null value. Below are the codes:
public MySqlDataReader SendTimeLogs(string fromDate, string toDate, int bioId)
{
using (var cn = new DatabaseConnection().ConnectToMySql())
{
const string query = #"SELECT MIN(scan_time) as 'Time In', MAX(scan_time) as 'Time Out',
TIMEDIFF(MAX(scan_time),MIN(scan_time)) as difference
FROM `filtered_dates`
WHERE bio_id = #bioId AND date BETWEEN #fromDate AND #toDate GROUP BY date ORDER BY date asc";
var cmd = new MySqlCommand(query, cn);
cn.Open();
cmd.Parameters.AddWithValue("#fromDate", fromDate);
cmd.Parameters.AddWithValue("#toDate", toDate);
cmd.Parameters.AddWithValue("#bioId", bioId);
return cmd.ExecuteReader();
}
}
private void SendEmail()
{
var rdr = new EmployeeDataAccess().GetBioIdEmail();
while (rdr.HasRows && rdr.Read())
{
dgvBioIdList.Rows.Add(rdr["bio_id"].ToString(), rdr["email_add"].ToString());
}
for (var i = 0; i < dgvBioIdList.Rows.Count; i++)
{
var message = "Time Logs for Bio ID: " +dgvBioIdList.Rows[i].Cells[0].Value;
var x = new FilteredDatesDataAccess();
var timeLogs = x.SendTimeLogs(dtpStart.Text, dtpStop.Text,
Convert.ToInt32(dgvBioIdList.Rows[i].Cells[0].Value));
var rec = dgvBioIdList.Rows[0].Cells[1].Value.ToString();
Console.WriteLine(message);
Console.WriteLine(rec);
while (timeLogs.HasRows && timeLogs.Read())
{
Console.WriteLine(timeLogs["Time In"] + #" - " + timeLogs["Time Out"]);
}
}
}
I get the Console.WriteLine(message); and Console.WriteLine(rec); just fine but my while loop is not being written in the console. Can you help? Thank you.
Related
I would like to make my not null DateTime column null when I do the sum of the entire table so that I do not get any value for date time 1/1/0001 12:00:00. I would like to add whatever possible statement into this method. I tried to do parse it but it doesn't work, but for Amount it's perfectly fine.
private void SumOfRecords_Button(object sender, RoutedEventArgs e)
{
ObservableCollection<Receipt> receipts = new ReceiptDAO().GetAllReceiptsFromPiName();
Receipt receipt = new Receipt();
if (receipt.DateTime != null)
{
Receipt receipt0 = new Receipt()
{
DateTime = DateTime.TryParse(),
Amount = new ReceiptDAO().SumOfRecords("Amount")
};
receipts.Add(receipt);
this.Dispatcher.Invoke(() => ReceiptList.ItemsSource = receipts);
}
}
This is the method for SumOfRecords where I am writing my query.
public double SumOfRecords(string columnName)
{
ObservableCollection<Receipt> receipts = new ReceiptDAO().GetAllReceiptsFromPiName();
Receipt receipt = new Receipt();
string commandstring;
commandstring = "select Sum(" + columnName + ") from " + getTable();
using (SQLiteConnection connection = ConnectToDatabase())
{
using (SQLiteCommand command = new SQLiteCommand(commandstring, connection))
{
using (SQLiteDataReader reader = command.ExecuteReader())
{
reader.Read();
return reader.GetDouble(0);
}
}
}
}
Just ignore dates when you calculate the sum. Assuming you're using sql server for database.
var where = " WHERE Table.Date <> '0001/01/01 00:00:00'";
commandstring = "select Sum(" + columnName + ") from " + getTable() + where;
You can pass where as a parameter to the method to make it reusable. Based on what database you're using, you may want look into date comparison. Otherwise the concept remains the same.
with a combo selected index changed event I am taking data from table in my labels all going well except the date. Problem: Label is showing date with 12:00 and I need only date (dd/MMM/yyyy) not with time 12:00. This date is perfect in column of table and also in gridview. Only the label shows it wrongly in the Label (AcPtRgDateLbl.Text).
here is the code:
private void AcPtPtrDd_SelectedIndexChanged(object sender, EventArgs e)
{
cmd = new SqlCommand("SELECT * FROM Patients where pt_ptr='" + AcPtPtrDd.Text.ToString() + "'", con);
con.Open();
cmd.ExecuteNonQuery();
SqlDataReader dr;
dr = cmd.ExecuteReader();
while (dr.Read())
{
string idn = (string)dr["pt_name"].ToString();
string idn1 = (string)dr["pt_date"].ToString();//Problem is here Please help to solve it.
string idn4 = (string)dr["pt_aid"].ToString();
string idn9 = (string)dr["pt_phone"].ToString();
AcPtNameLbl.Text = idn;
AcPtRgDateLbl.Text = idn1;
AcPtAidLbl.Text = idn4;
AcPtPhonLbl.Text = idn9;
if (AcPtAidLbl.Text == "-")
{
AcPtAidTxt.Enabled = false;
}
else
{
AcPtAidTxt.Enabled = true;
}
}
con.Close();
}
Tabel from SQL:
ALTER procedure [dbo].[pa_getPtAccountsDataLike]
#data nvarchar(50)
as
select
p.pta_id as 'ID',
p.pta_ptr as 'PtR',
p.pta_date as 'Date',
p.pta_fee as 'Fee',
p.pta_dis as 'Discount',
p.pta_aid as 'Aid',
p.pta_rcv as 'Receive',
p.pta_bal as 'Balance'
from PtAccounts p
where
p.pta_ptr like '%'+#data+'%'
or
p.pta_date like '%'+#data+'%'
order by p.pta_ptr desc
Try read as DateTime and then represent it as a string
string idn1 = Convert.ToDateTime(dr["pt_date"]).ToString("dd/MMM/yyyy");
More code (let's brush up your solution):
//DONE: required fields only; parametrized query
string sql =
#"SELECT pt_name,
pt_date,
pt_aid,
pt_phone
FROM Patients
WHERE pt_ptr = #pt_ptr";
//DONE: wrap IDisposable in using
using (var cmd = new SqlCommand(sql, con)) {
//TODO: cmd.Parameters.Add("#pt_ptr", AcPtPtrDd.Text, Rdbms_Type_Here);
// (explicit add) is a better implementation
cmd.Parameters.AddWithValue("#pt_ptr", AcPtPtrDd.Text);
using (var dr = cmd.ExecuteReader()) {
//DONE: we read at most one record only; no need in while
if (dr.Read()) {
AcPtNameLbl.Text = Convert.ToString(dr["pt_name"]);
AcPtRgDateLbl.Text = Convert.ToDateTime(dr["pt_date"]).ToString("dd/MMM/yyyy");
AcPtAidLbl.Text = Convert.ToString(dr["pt_aid"]);
AcPtPhonLbl.Text = Convert.ToString(dr["pt_phone"]);
}
else {
//DONE: what if we have an empty cursor?
AcPtNameLbl.Text = "";
AcPtRgDateLbl.Text = "";
AcPtAidLbl.Text = "-";
AcPtPhonLbl.Text = "";
}
AcPtAidTxt.Enabled = AcPtAidLbl.Text != "-";
}
}
Please try this
string idn1 = dr["pt_date"].ToString("dd/MMM/yyyy");
i would like to create an id generator based on their department selected from the dropdownlist. lets say my ddl has 3 departments (A,B,C) and when generating an id it will be A20181001 and then A20181002 upon submission but when i pick B from the ddl after sending A20181001 to the database, it will be B20181001.
so far i have created the code for the increment for the id without the departments. here is the code i did so far. (I used the date for today so the 20181001 is just an example):
void getMRF_No()
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
int mrf = 0;
int i;
string a;
//string x = Request.QueryString["BUnit"];
string mrfNo = "";
database db = new database();
string conn = dbe.BU();
SqlConnection connUser = new SqlConnection(conn);
SqlCommand cmd = connUser.CreateCommand();
SqlDataReader sdr = null;
string query = "SELECT TOP 1 MRF_NO FROM incMRF ORDER BY MRF_NO DESC";
connUser.Open();
cmd.CommandText = query;
sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr.GetInt32(0).ToString();
}
if (mrfNo == "")
{
mrfNo = Convert.ToString(year) + "" + 00;
}
mrf += 0;
i = Convert.ToInt32(mrfNo) + 1;
a = i.ToString();
txtMRFNo.Text = a;
connUser.Close();
}
any help to improve this code will be helpful. thank you :)
EDIT:
here is the dropdown list code:
void SelectBU()
{
string database = dbe.BU ();
using (SqlConnection con = new SqlConnection(database))
{
con.Open();
string query = "select BUnit from BusinessUnit";
using (SqlDataAdapter sda = new SqlDataAdapter(query, con))
{
DataSet ds = new DataSet();
sda.Fill(ds, "BUnit");
ddlBu.DataSource = ds;
ddlBu.DataTextField = "BUnit";
ddlBu.DataValueField = "BUnit";
ddlBu.DataBind();
selectOption(ddlBu, "Select Dept");
}
con.Close();
}
}
EDIT2: I will state what im searching for here incase some doesnt know or understand. What i want is upon selecting a department from a dropdownlist, for example i picked A. the textbox show show A2018102201. if i select B it should show B2018102201 and if its C then c2018102201. and it will change its number once i submit it to a database and a new form loads. So if A2018102201 is already in the database, then the text shown in the text box will be A2018102202. BUT if i select B then the textbox will show B2018102201 since it does not exist in the database yet.
First you should get max ID, then increase the numeric part of your Id, and If this is a multi-user application, you have to lock your table, because it might create many ID duplication, Therefore I'm not recommend to create ID like this on c#, it is better to create a Sequence on SQL server. but I wrote this sample for you, just call it with proper value.
static string getMRF_No(string prefixCharFromDropDownList)
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
string mrfNo = "";
SqlConnection connUser = new SqlConnection("Server=130.185.76.162;Database=StackOverflow;UID=sa;PWD=$1#mssqlICW;connect timeout=10000");
SqlCommand cmd = new SqlCommand(
$"SELECT MAX(MRF_NO) as MaxID FROM incMRF where MRF_NO like '{prefixCharFromDropDownList}%'"
,connUser
);
connUser.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr["MaxID"].ToString();
}
if (mrfNo == "")
{
mrfNo = prefixCharFromDropDownList + year + "000";
}
else
{
mrfNo = prefixCharFromDropDownList + (long.Parse(mrfNo.Substring(1)) + 1).ToString().PadLeft(2);
}
sdr.Close();
cmd = new SqlCommand($"INSERT INTO incMRF (MRF_NO) values ('{mrfNo}')",connUser);
cmd.ExecuteNonQuery();
connUser.Close();
//txtMRFNo.Text = prefixCharFromDropDownList + i.ToString();
return mrfNo;
}
I call this method on a console application as test.
static void Main(string[] args)
{
// send dropdown (selected char) as prefix to method
var newAId = getMRF_No("A");
var newAnotherAId = getMRF_No("A");
var newBId = getMRF_No("B");
var newAnotherAId2 = getMRF_No("A");
Console.ReadKey();
}
I'm trying to implement date-picker functionality in my project, but I can't do it quite right. I'm trying to pass the date-picker value in my oracle string so that it will compare with my db column and return results on the date criteria...
Whenever I pass it to the select statement it won't generate errors particularly but on button click it doesn't perform anything except it shows "not connected".
str = "Select * from sania.doctor where APPOINTMENT_DATE = "+ datepicker1.value;
It is clear it is logical mistake but I'm new to this C# concepts I need someone to tell me how to pass it and then display the results as well.
private void button1_Click(object sender, EventArgs e)
try
{
OracleCommand com;
OracleDataAdapter oda;
string ConString = "Data Source=XE;User Id=system;Password=sania;";
OracleConnection con = new OracleConnection(ConString);
{
// string id = dateTimePicker1.Text.Trim();
con.Open();
// str = "Select * from sania.doctor where APPOINTMENT_DATE = " + dateTimePicker1.value;
str = "select * from sania.doctor where APPOINTMENT_DATE to_date('"+dateTimePicker1.Value.ToString("yyyyMMdd") + "', 'yyyymmdd')";
com = new OracleCommand(str);
oda = new OracleDataAdapter(com.CommandText, con);
dt = new DataTable();
oda.Fill(dt);
Rowcount = dt.Rows.Count;
//int val = 0;
for (int i = 0; i < Rowcount; i++)
{
dt.Rows[i]["APPOINTMENT_DATE"].ToString();
//if (id == dateTimePicker1.Value)// this LINE SHOWS ERROR--because it is a string and I am using date with it. Don't know conversion
// {
// val = 1;
//}
}
// if (val == 0)
// { MessageBox.Show("INVALID ID"); }
// else
// {
DataSet ds = new DataSet();
oda.Fill(ds);
if (ds.Tables.Count > 0)
{
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
else { MessageBox.Show("NO RECORDS FOUND"); }
}
}
//}
catch (Exception)
{ MessageBox.Show("not connected"); }
}
Do not put values into SQL directly, use bind variables/parametes instead. For Oracle:
// :prm_Appointment_Date bind variable declared within the query
String str =
#"select *
from sania.doctor
where Appointment_Date = :prm_Appointment_Date";
....
using(OracleCommand q = new OracleCommand(MyConnection)) {
q.CommandText = str;
// datepicker1.Value passed into :prm_Appointment_Date via parameter
q.Parameters.Add(":prm_Appointment_Date", datepicker1.Value);
...
}
Doing like that you can be safe from either SQL Injection or Format/Culture differences
I've got a DataGridView that has 2 columns - product name and the quantity of it. So I grab each row in a foreach loop and calculate the price of it. I managed to do that but I can't seems to figure out how to store ALL the calculated rows into a single variable and insert them into a database.
This is what I have so far:
string cMedication = string.Empty;
string cQuantity = string.Empty;
string cAppointment = string.Empty;
foreach (DataGridViewRow row in this.dataPrescription.Rows)
{
cMedication = row.Cells[0].Value.ToString();
cQuantity = row.Cells[1].Value.ToString();
cAppointment = txtAppointmentID.Text;
if (cAppointment == "NO APPOINTMENT HAS BEEN MADE")
{
MessageBox.Show("Please make an appointment first at the Nurse counter", "WARNING");
}
else
{
//this.savePrescription(cMedication, cQuantity, cAppointment);
string strConnectionString = ConfigurationManager.ConnectionStrings["HConnection"].ConnectionString;
string strCalc = "SELECT medicationPrice FROM MEDICATION WHERE medicationName= ('" + cMedication + "')";
using (SqlConnection connection = new SqlConnection(strConnectionString))
{
using (SqlCommand cmdCalc = new SqlCommand(strCalc, connection))
{
connection.Open();
SqlDataReader readPrice = cmdCalc.ExecuteReader();
if (readPrice.Read())
{
string getPrice = readPrice["medicationPrice"].ToString();
double doublePrice = Convert.ToDouble(getPrice);
double doubleQuantity = Convert.ToDouble(cQuantity);
double result = doublePrice * doubleQuantity;
string answer = result.ToString();
//insert TOTAL amount to database below
}
readPrice.Close();
connection.Close();
}
}
}
}
If you're doing this kind of thing a lot then I would use some kind of ORM like Entity Framework (or write your own). Then you would just load / create entites and save them.
If that's overkill for what you're doing then you could build up an insert statement and execute it, much like you've done to query the medication price. Only as I've mentioned in the comment, use SqlParameters instead of string concatenation to avoid possible sql injection attacks.
Something like this (untested).
var builder = new StringBuilder("INSERT INTO MedicationLine (MedicationName, Quantity, Price) VALUES ");
int i = 0;
var parameters = new List<SqlParameter>();
foreach (DataGridViewRow row in this.dataPrescription.Rows)
{
string cAppointment = txtAppointmentID.Text;
if (cAppointment == "NO APPOINTMENT HAS BEEN MADE")
{
MessageBox.Show("Please make an appointment first at the Nurse counter", "WARNING");
return;
}
string cMedication = row.Cells[0].Value.ToString();
string cQuantity = row.Cells[1].Value.ToString();
i++;
string strConnectionString = ConfigurationManager.ConnectionStrings["HConnection"].ConnectionString;
string strCalc = "SELECT medicationPrice FROM MEDICATION WHERE medicationName = #medicationName";
using (SqlConnection connection = new SqlConnection(strConnectionString))
{
using (SqlCommand cmdCalc = new SqlCommand(strCalc, connection))
{
command.Parameters.Add(new SqlParameter("medicationName", cMedication);
connection.Open();
SqlDataReader readPrice = cmdCalc.ExecuteReader();
if (readPrice.Read())
{
string getPrice = readPrice["medicationPrice"].ToString();
double doublePrice = Convert.ToDouble(getPrice);
double doubleQuantity = Convert.ToDouble(cQuantity);
builder.AppendLine();
builder.Append("(";
builder.Append("#Name");
builder.Append(i);
builder.Append("#Qty");
builder.Append(i);
builder.Append("#Price");
builder.Append(i);
builder.Append("),";
parameters.Add(new SqlParameter("Name" + i.ToString(), medicationName);
parameters.Add(new SqlParameter("Qty" + i.ToString(), doubleQuantity);
parameters.Add(new SqlParameter("Price" + i.ToString(), doublePrice);
}
readPrice.Close();
connection.Close();
}
}
}
The idea is to end up with something like:
INSERT INTO MedicationLine (MedicationName, Quantity, Price) VALUES
(#Name1, #Qty1, #Price1),
(#Name2, #Qty2, #Price2),
(#Name3, #Qty3, #Price3),
...
Then execute it. Don't forget to trim the trailing comma.
using (var connection = new SqlConnection(strConnectionString))
{
using (var command = new SqlCommand(builder.ToString().TrimEnd(','), connection))
{
command.Parameters.AddRange(parameters.ToArray());
connection.Open();
int recordsAffected = command.ExecuteNonQuery();
}
}
**Disclaimer
Syntax may be wrong as done without an IDE!