I have a program that will retrieve student and class information.
I already use if (!reader.HasRows) to check if the student is existing but the problem is not all student is already registered in a certain class and I want it continue retrieving data even the values in the class information is Null. I am new to C# and any help and recommendation is deeply appreciated.
private void btnstudsearch_Click_1(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"data source = DELL-USER\SQLEXPRESS;integrated security = SSPI;database = Enrollment System");
DataTable dt = new DataTable();
con.Open();
SqlDataReader reader = null;
SqlCommand cmd = new SqlCommand("select tbl_studregs.fname, tbl_studregs.mname, tbl_studregs.lname, tbl_studregs.age, tbl_studregs.sex,
tbl_studregs.address, tbl_studregs.gname, tbl_studregs.gcnum, tbl_studregs.educlevel, tbl_class.yglevel, tbl_class.section from tbl_studregs
inner join tbl_class on tbl_studregs.classid = tbl_class.classid where tbl_studregs.studid = #id ", con);
cmd.Parameters.AddWithValue("#id", txtstudsearch.Text);
reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
MessageBox.Show("Student not found! Please recheck the student ID!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
ClearAllTextBox();
}
else
{
while (reader.Read())
{
txtstudfname.Text = reader.GetValue(0).ToString();
txtmname.Text = reader.GetValue(1).ToString();
txtstudlname.Text = reader.GetValue(2).ToString();
txtage.Text = reader.GetValue(3).ToString();
cboxsex.Text = reader.GetValue(4).ToString();
rtxtaddress.Text = reader.GetValue(5).ToString();
txtgname.Text = reader.GetValue(6).ToString();
txtgcnum.Text = reader.GetValue(7).ToString();
cboxstudlevel.Text = reader.GetValue(8).ToString();
txtstudyearlev.Text = reader.GetValue(9).ToString();
txtstudsec.Text = reader.GetValue(10).ToString();
}
}
}
If I understand correctly, you want to retrieve the information for a student even if there isn't a class connected to them on the tbl_class table. I think it would help most you to look up the difference between different SQL join operations.
It looks like what you want is a left join instead of an inner join in your SQL query, although it may depend on what your database looks like.
Related
I have a stored procedure created in my SQL Server 2012 database that selects data from multiple tables. In C#, I use this procedure to show data in a datagridview.
Issue: when I execute the query in SQL Server, I get the correct result which returns 3 rows, but in C#, it returns only 2 rows.
Query:
SELECT DISTINCT
Employee.Employee_No AS 'Badge'
,Employee.Employee_Name_Ar AS 'Emp Name'
,Employee.Basic_Salary AS 'Basic'
,Employee.Current_Salary AS 'Current'
,Attendance.Present
,Attendance.Leave
,Attendance.Othe_Leave AS 'OL'
,Pay_Slip.Salary_Amount AS 'Sal. Amt.'
,(ISNULL(Pay_Slip.OverTime1_Amount, 0.00) + ISNULL(Pay_Slip.OverTime2_Amount, 0.00)) AS 'O/T Amt.'
,(ISNULL(Pay_Slip.Salary_Amount, 0.00) + ISNULL(ISNULL(Pay_Slip.OverTime1_Amount, 0.00) + ISNULL(Pay_Slip.OverTime2_Amount, 0.00), 0.00)) AS 'Sal. & O/T'
,Pay_Slip.Trasnport AS 'Allow'
,Pay_Slip.CostofLiving AS 'O.Allow'
,Pay_Slip.Gross_Salary AS 'T Salary'
,Pay_Slip.Insurance1_Amount AS 'ss 7%'
,Pay_Slip.Insurance2_Amount AS 'ss 11%'
,(ISNULL(Pay_Slip.Insurance1_Amount, 0.00) + ISNULL(Pay_Slip.Insurance2_Amount, 0.00)) AS 'Total s.s'
,Pay_Slip.Tax
,Pay_Slip.Personal_Loans AS 'Advance'
,Pay_Slip.Other_Deductions AS 'Ded.'
,Pay_Slip.Net_Salary AS 'Net'
FROM Pay_Slip
LEFT JOIN Employee ON Pay_Slip.Employee_No = Employee.Employee_No
LEFT JOIN Attendance ON Pay_Slip.Employee_No = Attendance.Employee_No
WHERE Pay_Slip.Month = '5'
AND Pay_Slip.Year = '2020'
AND Attendance.Month = '5'
AND Attendance.Year = '2020'
Executing this query in SQL Server returns 3 rows which are the employee slips on May-2020 (They all have values in May-2020).
C# code:
private void dateTimePicker_ReportDate_ValueChanged(object sender, EventArgs e)
{
try
{
DateTime date = dateTimePicker_ReportDate.Value;
String Month = dateTimePicker_ReportDate.Value.ToString("MM");
String Year = dateTimePicker_ReportDate.Value.ToString("yyyy");
String str = "server=localhost;database=EasyManagementSystem;User Id=Jaz;Password=Jaz#2020;Integrated Security=True;";
String query = "Execute EMP_PAY_ATT_Selection #Month, #Year";
SqlConnection con = null;
con = new SqlConnection(str);
SqlCommand cmd= new SqlCommand(query, con);
cmd.Parameters.Add("#Month", SqlDbType.Int).Value = Convert.ToInt32(Month);
cmd.Parameters.Add("#Year", SqlDbType.Int).Value = Convert.ToInt32(Year);
SqlDataReader sdr;
con.Open();
sdr = cmd.ExecuteReader();
if (sdr.Read())
{
DataTable dt = new DataTable();
dt.Load(sdr);
dataGridView_Report.DataSource = dt;
dataGridView_Report.EnableHeadersVisualStyles = false;
dataGridView_Report.ColumnHeadersDefaultCellStyle.BackColor = Color.LightBlue;
}
else
{
dataGridView_Report.DataSource = null;
dataGridView_Report.Rows.Clear();
}
con.Close();
}
catch (Exception es)
{
MessageBox.Show(es.Message);
}
}
Again, when running this, it only returns 2 rows on the datagridview. While it should be 3 rows.
These are the tables:
The DbDataReader.Read method advances the reader to the next record.
There is no way to rewind a data reader. Any methods that you pass it to will have to use it from whatever record it is currently on.
If you want to pass the reader to DataTable.Load(), do not Read from it yourself. If you merely want to know if it contains records, use HasRows.
I am trying to update a databse entry under a specific id in my table when the users enter their ID number in a textBox.
At the moment it updates but updates all entries in my table except the entry containing the users ID number.
This is the code I am currently using:
private void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=DEVELOPMENT\ACCESSCONTROL;Initial Catalog=ACCESSCONTROL;User ID=sa;Password=P#55w0rd123");
SqlCommand check_User_Name = new SqlCommand("SELECT Id FROM NewVisitor WHERE (IDNumber = #IDNumber)", con);
check_User_Name.Parameters.AddWithValue("#IDNumber", idNumber_TxtBox.Text);
con.Open();
int UserExist = (int)check_User_Name.ExecuteScalar();
if (UserExist > 0)
{
var connetionString = #"Data Source=DEVELOPMENT\ACCESSCONTROL;Initial Catalog=ACCESSCONTROL;User ID=sa;Password=P#55w0rd123";
var sql = "UPDATE NewVisitor SET PersonVisit = #PersonVisit, PurposeVisit = #PurposeVisit, Duration = #Duration, Disclaimer = #Disclaimer";
try
{
using (var connection = new SqlConnection(connetionString))
{
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#PersonVisit", SqlDbType.NVarChar).Value = personVisiting_TxtBox.Text;
command.Parameters.Add("#PurposeVisit", SqlDbType.NVarChar).Value = purposeOfVisit_CMBox.SelectedItem;
command.Parameters.Add("#Duration", SqlDbType.Date).Value = duration_dateTimePicker1.Value.Date;
command.Parameters.Add("#Disclaimer", SqlDbType.NVarChar).Value = disclaimer_CHKBox.Checked;
connection.Open();
command.ExecuteNonQuery();
}
}
}
The whole table has many more fields but would like to just update the above fields within that specific ID.
Thanks
You forgot the WHERE clause on the UPDATE statement, telling it specifically which records to update. It sounds like you just want to add the exact same WHERE clause that you have on your SELECT:
var sql = "UPDATE NewVisitor SET PersonVisit = #PersonVisit, PurposeVisit = #PurposeVisit, Duration = #Duration, Disclaimer = #Disclaimer WHERE (IDNumber = #IDNumber)";
And don't forget to add the paramter for it:
command.Parameters.Add("#IDNumber", SqlDbType.Int).Value = idNumber_TxtBox.Text;
You may need to convert the input value to an integer first, I'm not 100% certain (it's been a while since I've had to use ADO.NET directly). Something like this:
if (!int.TryParse(idNumber_TxtBox.Text, out var idNumber))
{
// input wasn't an integer, handle the error
}
command.Parameters.Add("#IDNumber", SqlDbType.Int).Value = idNumber;
I think my code is correct but why error syntax near 'po_no' check my code please. What is the problem with my code with this kind of error? Do I need to JOIN or two queries? I just want to display the two table using inner join
try
{
if (cb_po_search.Text == "")
{
MessageBox.Show("Please Enter to Search!");
}
else
{
string strPRSconn = ConfigurationManager.ConnectionStrings["POSdb"].ConnectionString;
SqlConnection sc = new SqlConnection(strPRSconn);
sc.Open();
string strQry = "SELECT dbo.POMain.po_no, dbo.POMain.issuing_month, dbo.POMain.supplier, dbo.POMain.model, dbo.POMain.category, dbo.POMain.req_number, dbo.POMain.shipment, dbo.POMain.production_month, dbo.POMain.req_time_arrival, dbo.POMain.req_department, dbo.POMain.lead_time, dbo.POMain.order_desc, dbo.POMain.date_emailed, dbo.POMain.date_confirmed, dbo.POMain.date_recieved, dbo.POMain.assumed_arrival, dbo.Shipping.invoice, dbo.Shipping.loading_date, dbo.Shipping.etd, dbo.Shipping.eta_manila, dbo.Shipping.eta_tstech, dbo.Shipping.ata_tstech, dbo.Shipping.shipping_status, dbo.Shipping.remarks FROM dbo.POMain INNER JOIN dbo.Shipping ON dbo.POMain.po_no = dbo.Shipping.po_noWHERE po_no= '" + cb_po_search.Text + "'";
SqlCommand scmd = new SqlCommand(strQry, sc);
SqlDataAdapter da = new SqlDataAdapter(strQry, sc);
DataTable dt = new DataTable();
SqlDataReader dr = scmd.ExecuteReader();
while (dr.Read())
{
//purchase order
tb_ponumber2.Text = (dr["po_no"].ToString());
tb_reqnumber2.Text = (dr["req_number"].ToString());
cb_supplier2.Text = (dr["supplier"].ToString());
cb_model2.Text = (dr["model"].ToString());
cb_category2.Text = (dr["category"].ToString());
cb_shipment2.Text = (dr["shipment"].ToString());
ta_description2.Text = (dr["order_desc"].ToString());
tb_leadtime2.Text = (dr["lead_time"].ToString());
tb_request2.Text = (dr["req_department"].ToString());
dt_time_arrival2.Value = DateTime.Parse(dr["req_time_arrival"].ToString());
dt_arrival2.Value = DateTime.Parse(dr["assumed_arrival"].ToString());
dt_confirmed2.Value = DateTime.Parse(dr["date_confirmed"].ToString());
dt_email2.Value = DateTime.Parse(dr["date_emailed"].ToString());
dt_production_month2.Value = DateTime.Parse(dr["production_month"].ToString());
dt_recieve2.Value = DateTime.Parse(dr["date_recieved"].ToString());
dt_issuing_month2.Value = DateTime.Parse(dr["issuing_month"].ToString());
}
sc.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Your code is asking for an SQL Injection, use parametized queries instead with SqlParameter class.
Edit. Your query have a missing equals sign at the end. Things that woudn't happen using parametized queries ;-)
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06
i have a form with a collection of about five drop down . i have my query as follows .
string sql = "SELECT a.clientID ,a.[cname],b.bid,b.[bname],c.contactID, c.[name] FROM "
+ " dbo.[CLIENT] AS a INNER JOIN dbo.[BRANCH] AS b "
+ "ON a.clientID = b.clientID JOIN dbo.[CONTACT] AS "
+ " c ON b.bid = c.bid ORDER BY a.clientID ";
i then followed and bind my drop down individually to their respective columns as follows.
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
SqlDataReader reader = cmd.ExecuteReader();
drClient.Enabled = true;
drClient.DataSource = reader;
drClient.DataTextField = "cname";
drClient.DataValueField = "clientID";
drClient.DataBind();
drBranch.Enabled = true;
drBranch.DataSource = reader;
drBranch.DataTextField = "bname";
drBranch.DataValueField = "bid";
drBranch.DataBind();
drContact.Enabled = true;
drContact.DataSource = reader;
drContact.DataTextField = "name";
drContact.DataValueField = "contactID";
drContact.DataBind();
drEmail.Enabled = true;
drEmail.DataSource = reader;
drEmail.DataTextField = "name";
drEmail.DataValueField = "contactID";
drEmail.DataBind();
drFax.Enabled = true;
drFax.DataSource = reader;
drFax.DataValueField = "contactID";
drFax.DataTextField = "name";
drFax.DataBind();
when i run this, only the first drop down bind successfully. The rest don't. I also try to loop through the reader by adding
while(reader.read())
{
then my bindings
}
the above also fails. I though of looping as below as well.
while(read.HasRows)
{
}
it still fails. I am confused,any help would be appreciated. thanks
Reader is readonly and forward only that's why only first dropdonw get filled with data and others are empty.
You can use datset or Datatable for same problem .
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
Dataset dsresult = cmd.ExecuteDataset();
If(dsResult !=null)
{
if(dsResult.Rows.count>0)
{
drClient.Enabled = true;
drClient.DataSource = dsResult.Tables[0] ;
drClient.DataTextField = Convert.ToString(ds.Tables[0].Columns["cname"]);
drClient.DataValueField = ds.Tables[0].Columns["clientID"] ;
drClient.DataBind();
}
}
Datareader is connected architecture needs continuous connection and fetches one row at a time in forward mode better use dataset which uses disconnected architecture and can be used for retrieving data multiple times.
This seems clear postback problem.
Bind your drop down on !postback.
Eg.
if(!IsPostBack)
{
populateDdl();
}
Either you will have to make a seperate reader for each binding
or you can do this by filling a datatable ( i would prefer this). Like,
DataTable dt = new DataTable();
using (SqlDataAdapter a = new SqlDataAdapter(sql, connection))
{
a.Fill(dt);
}
drClient.DataSource = dt;
drClient.DataBind();
drBranch.DataSource = dt;
drBranch.DataBind();
drContact.DataSource = dt;
drContact.DataBind();
drFax.DataSource = dt;
drFax.DataBind();
Your choices are to either rerun/refill it or create separate readers or better yet fill a datatable instead and then you can reuse the datatable.
Is it possible to connect to a local MDB file and pick a single bit of info out of it ?
I have a table in a .mbd file with a single bit of info in it. I would like to have that record be output into a disabled textbox for a reference. I believe I can get the DB open, and run the query but no idea what I need to read from it.
thanks
var myDataTable = new DataTable();
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var adapter = new OleDbDataAdapter(query, conection);
OleDbCommandBuilder oleDbCommandBuilder = new OleDbCommandBuilder(adapter);
}
To simply read a single field on your database table you could use an OleDbDataReader that could loop over the result and return the field required..
var myDataTable = new DataTable();
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var command = new OleDbCommand(query, conection);
var reader = command.ExecuteReader();
while(reader.Read())
textBox1.Text = reader[0].ToString();
}
if you have just one record and just one field then a better solution is the method ExecuteScalar
conection.Open();
// A query that returns just one record composed of just one field
var query = "Select siteid From n_user where userid=1";
var command = new OleDbCommand(query, conection);
int result = (int)command.ExecuteScalar(); // Supposing that siteid is an integer
Probably I should also mention that ExecuteScalar returns null if the query doesn't find a match for the userid, so it is better to be careful with the conversion here
object result = command.ExecuteScalar();
if( result != null)
int userID = (int)result;
.....
Yes very possible. Just have the adapter fill the DataTable, also I don't think you'll need the OleDbCommandBuilder.
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var adapter = new OleDbDataAdapter(query, conection);
adapter.Fill(myDataTable);
myTextBox.Text = myDataTable.Rows[0][0].ToString();
}
Also I think using ExecuteScalar would be a better solution, but my answer was tailored to the objects you had already instantiated.
You could use OleDbCommand.ExecuteScalar to retrieve a single value. It is returned as an object and you could cast it to the correct type.
Are you looking for stm like this?
OleDbCommand cmd = new OleDbCommand();
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
// read ur stuff here.
}