c# fetching database into SQL Server datatable - c#

I have a problem with this code... I don't have the slightest clue for what is happening...
When I run this code in Visual Studio, I get an error saying:
System.InvalidCastException: 'Object cannot be cast from DBNull to other types.'
And here's the code:
conn.Open();
SqlCommand com = new SqlCommand("update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='" + comboBox1.Text + "'", conn);
SqlDataAdapter da = new SqlDataAdapter("Declare #startdate smalldatetime declare #enddate smalldatetime set #startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "') set #enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "') SELECT DATEDIFF(DAY, #startdate+2, #enddate)as timepassedd", conn);
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow DR in dt.Rows)
{
int date;
date = Convert.ToInt32(DR["timepassedd"]);
if (date > 0)
{
com = new SqlCommand("DELETE lend WHERE client_name ='"+comboBox1.Text+"'" +
"UPDATE book_list set book_stock = book_stock 1 WHERE book_name ='" + comboBox1.Text + "'",conn);
com.ExecuteNonQuery();
MessageBox.Show("You Returned the book " + date + " Days Late!" +
"please pay the fee to the front desk");
UserPanel u = new UserPanel();
u.Show();
this.Hide();
}
else if (date <= 0)
{
com = new SqlCommand("DELETE lend WHERE client_name ='" + comboBox1.Text + "'" +
"UPDATE book_list set book_stock = book_stock 1 WHERE book_name ='" + comboBox1.Text + "'", conn);
com.ExecuteNonQuery();
MessageBox.Show("You returned the book " + date + " Days Late!" +
"please pay the fee to the front desk");
UserPanel u = new UserPanel();
u.Show();
this.Hide();
}
}
conn.Close();
Thanks in advance

conn.Open();
SqlCommand com = new SqlCommand("update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='" + comboBox1.Text + "'", conn);
SqlDataAdapter da = new SqlDataAdapter("Declare #startdate smalldatetime declare #enddate smalldatetime set #startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "') set #enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "') SELECT DATEDIFF(DAY, #startdate+2, #enddate)as timepassedd", conn);
DataSet ds = new DataSet();
da.Fill(ds);
if(ds.Tables.Count == 1)
{
if(ds.Tables[0].Rows.Count > 0)
{
foreach(DataRow dr in ds.Tables[0].Rows)
{
if(dr.ItemArray.Length > 0)
{
if(dr["timepassedd"] != DBNull.Value)
{
int date;
date = Convert.ToInt32(Dr["timepassedd"]);
if (date > 0)
{
com = new SqlCommand("delete lend where client_name ='" + comboBox1.Text + "'" +
"UPDATE book_list set book_stock = book_stock 1 WHERE book_name ='" + comboBox1.Text + "'", conn);
com.ExecuteNonQuery();
MessageBox.Show("You Returned the book " + date + " Days Late!" +
"please pay the fee to the front desk");
UserPanel u = new UserPanel();
u.Show();
this.Hide();
}
else if (date <= 0)
{
com = new SqlCommand("delete lend where client_name ='" + comboBox1.Text + "'" +
"UPDATE book_list set book_stock = book_stock 1 WHERE book_name ='" + comboBox1.Text + "'", conn);
com.ExecuteNonQuery();
MessageBox.Show("You Returned the book " + date + " Days Late!" +
"please pay the fee to the front desk");
UserPanel u = new UserPanel();
u.Show();
this.Hide();
}
}
}
}
}
}
conn.Close();
You should check for DBNull value, if the column is null-able in the database a DBNull.Value will be returned instead! So you should check this column for such a value before dealing with it
Also, you shouldn't accept values from the user input and directly injecting them into the SQL query! ADO.Net. Has something called Sql Parameters it can be found in the property Parameters in the SqlCommand class. You should use this property to add values from user as parameters to the query
For Example, client name can be added like this:
com.Parameters.Add(new SqlParameter("client_name", comboBox1.Text));
Now you tell the Sql Command that the value is actually presented in the SqlParameters collection like this:
SqlCommand com = new SqlCommand("update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='#client_name'", conn);
Take a look at this question Why do we always prefer using parameters in the SQL statements?
This is a MSDN reference for the Parameters property

Run code below the answer will be obvious :
string sql1 = "update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='" + comboBox1.Text + "'";
Console.WriteLine(sql1);
Console.ReadLine();
SqlCommand com = new SqlCommand(sql1, conn);
string sql2 = "Declare #startdate smalldatetime declare #enddate smalldatetime set #startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "') set #enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "') SELECT DATEDIFF(DAY, #startdate+2, #enddate)as timepassedd"
Console.ReadLine();
SqlDataAdapter da = new SqlDataAdapter(sql2, conn);

set #startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "')
set #enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "')
a) vulnerable to unexpected behaviour if comboBox1.Text was ever to contain ' characters
b) both will result in #startdate or #enddate being NULL if there are no records matching what's selected in the combobox, which then produces a NULL value for '#datepassedd', hence your error when trying to convert to an int.
c) you don't need to query the database twice, you can just do
select DATEDIFF(DAY, date_lended+2, date_back) as timepassedd FROM dbo.lend where client_name = #clientName
(#clientName can then be added a as parameter)
In this case, there will be no rows returned if no records match the name. BTW there was never any need to use a DataTable and iterate through the records, as your query as it is now only ever returns a single row.

Related

Check if value input in textbox exists in database and insert if not

How to check if the text I input in textbox already exists in database and if so update only the data or anything solution you recommend and if not the data will automatically insert into database? Here is my code:
cn.Open();
cm = new MySqlCommand("SELECT * FROM tblcustomer WHERE fullname LIKE '" + txtCustomer.Text + "'", cn);
dr = cm.ExecuteReader();
dr.Read();
if (dr.HasRows)
{
cm = new MySqlCommand("UPDATE tblcustomer SET fullname = '" + txtCustomer.Text + "' WHERE id LIKE '" + lblCustomerId.Text + "'", cn);
cm.ExecuteNonQuery();
}
else
{
cm = new MySqlCommand("INSERT INTO tblcustomer(fullname) VALUES ('" + txtCustomer.Text + "')", cn);
cm.ExecuteNonQuery();
}
dr.Close();
cn.Close();
Change your SQL to this:
"INSERT INTO tblcustomer fullname VALUES" + txtCustomer.Text + "
ON DUPLICATE KEY UPDATE fullname= " + txtCustomer.Text
Pseudo, didn't validate this, but it is sort of the right idea, of what you want. And does it in a single connection attempt to the DB.
You can find a guide here:
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

Insert incremented ID from the tbl_project to tbl_expense it must have same ID. I use PKey & Fkey the ID must be returned

There is no error in this code. The only concern I face is when I try to save in the database the FK won't get the id of PK. I already setup my database relationship and it connect id - projectid.
if (textID.Text == "" && textProject.Text == "" && textAmount.Text == "")
{
MessageBox.Show("Please Enter Details..!");
}
else
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM tbl_project WHERE Contract_ID = '" + textID.Text + "'", conn);
DataTable datatbl = new DataTable();
adapter.Fill(datatbl);
if (datatbl.Rows.Count == 1)
{
MessageBox.Show("Contract ID Already Exist!!");
}
else
{
SqlDataAdapter adap1 = new SqlDataAdapter("INSERT INTO tbl_project(Contract_ID,Contract_Amount,Contractor,Project_Name,Start_Date,End_Date,Year,Address,Remarks,Status)VALUES('" + textID.Text + "','" + textAmount.Text + "','" + textContract.Text + "','" + textProject.Text + "','" + dateTimePicker1.Value.Date + "','" + dateTimePicker2.Value.Date + "','" + textYear.Text + "','" + textAddress.Text + "','" + textOthers.Text + "','" + comboBox5.Text + "')", conn);
DataTable fill1 = new DataTable();
adap1.Fill(fill1);
SqlDataAdapter adap2 = new SqlDataAdapter("INSERT INTO tbl_expense(CONTRACT,CONTRACT_ID,CONTRACTOR,PROJECT_STATUS,COVERED_PERIOD,END_PERIOD,PROJECT_AMOUNT)VALUES('" + textProject.Text + "','" + textID.Text + "','" + textContract.Text + "','" + comboBox5.Text + "','" + dateTimePicker1.Value.Date + "','" + dateTimePicker2.Value.Date + "','" + textAmount.Text + "')", conn);
DataTable data2 = new DataTable();
adap2.Fill(data2);
MessageBox.Show("Project Details Save...");
clear();
refresh();
}
}
From the information you've provided, it seems you are creating a value in two tables based on Contract_Id column and you are checking if the record already exists, you do not insert the records, otherwise you post the records.
Since, I cannot see the relationship between tbl_project and tbl_expense, I assume you are trying to insert Contract_Id as a foreign key in both the tables.
If that is the case, then I would suggest use below version of the code.
public void InsertIfNotExists()
{
if (textID.Text == "" && textProject.Text == "" && textAmount.Text == "")
{
MessageBox.Show("Please Enter Details..!");
}
else
{
using(var connection = new SqlConnection(DbConnectionString)) // Pass DbConnectionString for your SQL server instance
{
var query = #"
IF NOT EXISTS (SELECT * FROM tbl_project WHERE Contract_ID = #Contract_ID)
BEGIN
-- Here we are checking if the row already exists for the variable #Contract_ID
INSERT INTO tbl_project (Contract_ID, Contract_Amount, Contractor, Project_Name, Start_Date, End_Date, Year, Address, Remarks, Status)
VALUES (#Contract_ID, #Contract_Amount, #Contractor, #Project_Name, #Start_Date, #End_Date, #Year, #Address, #Remarks, #Status);
-- We are inserting the values since Contract_ID was not matched in the database.
INSERT INTO tbl_expense (CONTRACT, CONTRACT_ID, CONTRACTOR, PROJECT_STATUS, COVERED_PERIOD, END_PERIOD, PROJECT_AMOUNT)
VALUES (#CONTRACT, #CONTRACT_ID, #CONTRACTOR, #PROJECT_STATUS, #COVERED_PERIOD, #END_PERIOD, #PROJECT_AMOUNT);
-- We are inserting expense based on Contract_ID
END;
"
;
using (var cmd = new SqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("#Contract_ID", textID.Text);
cmd.Parameters.AddWithValue("#Contract_Amount", textAmount.Text);
cmd.Parameters.AddWithValue("#Contractor", textContract.Text);
cmd.Parameters.AddWithValue("#Project_Name", textProject.Text);
cmd.Parameters.AddWithValue("#Start_Date", dateTimePicker1.Value.Date);
cmd.Parameters.AddWithValue("#End_Date", dateTimePicker2.Value.Date);
cmd.Parameters.AddWithValue("#Year", textYear.Text);
cmd.Parameters.AddWithValue("#Address", textAddress.Text);
cmd.Parameters.AddWithValue("#Remarks", textOthers.Text);
cmd.Parameters.AddWithValue("#Status", comboBox5.Text);
cmd.Parameters.AddWithValue("#CONTRACT", textProject.Text);
cmd.Parameters.AddWithValue("#CONTRACTOR", textContract.Text);
cmd.Parameters.AddWithValue("#PROJECT_STATUS", comboBox5.Text);
cmd.Parameters.AddWithValue("#COVERED_PERIOD", dateTimePicker1.Value.Date);
cmd.Parameters.AddWithValue("#END_PERIOD", dateTimePicker2.Value.Date);
cmd.Parameters.AddWithValue("#PROJECT_AMOUNT", textAmount.Text);
connection.Open();
var rA = cmd.ExecuteNonQuery();
connection.Close();
MessageBox.Show(rA > 0 ? "Data Successfully saved!" : "Data already exists!");
}
}
}
}
In the code above, we are formulating the SQL Statement in a way, that you do not have to fetch and compare and then post to the database, saves you from the round trips for a simple operation.
Also, you'll notice, we are using parameterized query, where we are passing the parameters in the SQL statement, as mentioned in the comments by #Always Learning, it is a good thing from guys who try to mess around with your database, this will prevent SQL Injections.

Fill DataTable with two queries in C#

I have multiple tables in a SQL Server database and I am trying to fill a DataTable with two queries on two tables.
This is my code:
String qry = "SELECT Count(*) FROM boss WHERE username ='" + textBox1.Text + "'and password ='" + textBox2.Text + "'; SELECT Count(*) FROM employee WHERE first_name ='" + textBox1.Text + "'and password ='" + textBox2.Text + "' ";
SqlConnection con = new SqlConnection(#"Data Source=(local);Initial Catalog=my_pro;Integrated Security=True");
SqlDataAdapter sda = new SqlDataAdapter(qry, con);
DataTable dt = new DataTable();
sda.Fill(dt);
But this shows me data from boss table. What should I do?
Try this:
String qry = "SELECT Count(*) FROM boss WHERE username ='" + textBox1.Text +
"'and password ='" + textBox2.Text + "' UNION ALL SELECT Count(*) FROM
employee WHERE first_name ='" + textBox1.Text + "'and password ='" + textBox2.Text + "' ";
You need to change the query,
SELECT (
SELECT COUNT(*)
FROM boss
) AS count1,
(
SELECT COUNT(*)
FROM employee
) AS count2
WHERE username ='" + textBox1.Text + "'and password ='" + textBox2.Text + "';
You can use Subquery
SELECT BossCount=(
SELECT COUNT(*)
FROM boss
WHERE username ='" + textBox1.Text + "'and password ='" + textBox2.Text + "'
) ,
EmployeeCount=(
SELECT COUNT(*)
FROM employee
boss WHERE first_name ='" + textBox1.Text + "'and password ='" + textBox2.Text + "'
)

SQL Query Command not working but does not give error SQL Server

I am developing a database application in C#.NET and SQL Server 2012.
Some of my SQL statements are not working properly . When I execute the code it does not give any error. But when I try to delete something or Update a record, I does not do that. The code lies below:
public void updateFinalTable()
{
DialogResult result = MessageBox.Show("Please make sure no fields are empty or they will get changed. \n\t\t Do you want to continue?",
"Important Note",
MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
try
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConString"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("UPDATE fianlTable SET AccountNumber='" + textBox1.Text + "', Date='" + dateTimePicker1.Value.ToString("MM/dd/yyyy") + "', CustomerName='" + textBox3.Text + "' , Debit='" + txtDebit.Text + "', Credit='" + txtCredit.Text + "', Balance='" + txtBalance.Text + "' WHERE Id LIKE '" + textBox4.Text + "' ", con);
cmd.ExecuteNonQuery();
this.fianlTableBindingSource.AddNew();
DataTable dt = new DataTable();
SqlDataAdapter sda = new SqlDataAdapter("select * from fianlTable WHERE (UserName LIKE '" + LoginSession.UserID + "')", con);
sda.Fill(dt);
dataGridView1.DataSource = dt;
refresh();
con.Close();
MessageBox.Show("Record Updated Successfully!");
catch (Exception)
{
MessageBox.Show("Record Could Not be updated...! ");
}
}
}
Similar is the case with delete operation . Both codes give no error but inside the database no change is observed.
You have used Like in your where condition instead of =. So your code should be like this -
SqlCommand cmd = new SqlCommand("UPDATE fianlTable SET AccountNumber='" + textBox1.Text + "', Date='" +
dateTimePicker1.Value.ToString("MM/dd/yyyy") + "', CustomerName='" +
textBox3.Text + "' , Debit='" + txtDebit.Text + "', Credit='" +
txtCredit.Text + "', Balance='" + txtBalance.Text +
"' WHERE Id = '" + textBox4.Text + "' ", con);
ATTENTION This type of query potentially lead to SQL Injection. You better go with parametrized queries, like this -
string qry = = "UPDATE fianlTable SET AccountNumber = #accnt, CustomerName = #cname Where ID = #id)";
SqlCommand cmd = new SqlCommand(qry, con);
cmd.Parameters.AddWithValue("#accnt", textBox1.Text);
cmd.Parameters.AddWithValue("#cname", textBox3.Text);
cmd.Parameters.AddWithValue("#id", textBox4.Text);
cmd.ExecuteNonQuery();

Roundup in an update sql query

I have a sql column that is set to money, this has four numbers after the decimal point. I am calculating this column in an update query, I would like to roundup this column. example: 2388.6796, should be 2389
Math.Ceiling(0.5);
SqlCommand cmd1 = new SqlCommand("UPDATE Products SET [ThirdPartyRate] = 'Ceiling(" + GridView1.Rows[SelectedIndex].Cells[6].Text.ToString() + "' * [Price]) WHERE [Supplier] like '" + GridView1.Rows[SelectedIndex].Cells[0].Text.ToString() + "' ", con);
Use:
CEILING ( numeric_expression )
In principle you then do: UPDATE TABLE Products SET rounded_val=CEILING(not_rounded_val);
SqlCommand cmd1 = new SqlCommand("UPDATE Products SET [ThirdPartyRate] = CEILING(" +
GridView1.Rows[SelectedIndex].Cells[6].Text.ToString() +
" * [Price]) WHERE [Supplier] like '" +
GridView1.Rows[SelectedIndex].Cells[0].Text.ToString() + "' ", con);

Categories

Resources