Can't seem to insert date into SQL Server database - c#

I have created a table tblAttendence in the database that has 2 columns: Date (datetime) and RegNo (int). I have to insert the current date & time and a registration number from a label in the form.
C# code:
private void btnMarkAtt_Click(object sender, EventArgs e)
{
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
sqlCon.Open();
SqlCommand sqlCmd = new SqlCommand("MarkAtt", sqlCon);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#Date", DateTime.Now);
sqlCmd.Parameters.AddWithValue("#RegNo", int.Parse(lblRegNo.Text));
sqlCmd.ExecuteNonQuery();
MessageBox.Show("Attendance marked successfully!");
}
}
Stored procedure MarkAtt:
ALTER PROCEDURE [dbo].[MarkAtt]
#Date DATETIME,
#RegNo INT
AS
INSERT INTO tblAttendence(Date, RegNo)
VALUES (#Date, #RegNo)
There is no error shown in the code. The debugging doesn't stop to show an error. When I press the button, just nothing happens (neither the data is inserted, nor the message box is shown).
I can't seem to find out what is going on. The connection string is correct (I have used it in the same form and it works). Is there something wrong with the connection? Or the stored procedure? Or anything else that I am missing?

Related

I cannot save data to my SQL database using C#

I am new to C#. I am trying to save the numbers into a SQL Server database table (locally) but I get an error:
Cannot insert the value NULL into column
My code:
private void SaveBtn_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\fn1965\Desktop\Work\TESTDB\NumDB.mdf;Integrated Security=True;Connect Timeout=30");
conn.Open();
string insert_query = "INSERT into [NumericTable] (Num1, Num2, Total) VALUES (#Num1, #Num2, #Total)";
SqlCommand cmd = new SqlCommand(insert_query, conn);
cmd.Parameters.AddWithValue("#Num1", textBox1.Text);
cmd.Parameters.AddWithValue("#Num2", textBox2.Text);
cmd.Parameters.AddWithValue("#Total", textBox3.Text);
cmd.ExecuteNonQuery();
MessageBox.Show("Record saved");
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show("EROR:"+ ex.ToString());
}
}
Table schema
You can see in the image that the column Id is the only one that does not support null values. Since the column is not identity and as you are not providing a value on your insert, then the INSERT fail with the given exception. This code will work (only if there isn't a record with Id = 1 already):
string insert_query = "INSERT into [NumericTable] (Num1,Num2,Total, Id) Values (#Num1,#Num2,#Total, #id)";
SqlCommand cmd = new SqlCommand(insert_query, conn);
cmd.Parameters.AddWithValue("#Num1", textBox1.Text);
cmd.Parameters.AddWithValue("#Num2", textBox2.Text);
cmd.Parameters.AddWithValue("#Total", textBox3.Text);
cmd.Parameters.AddWithValue("#Id", 1);
cmd.ExecuteNonQuery();
I assume that this is obviously not the desired fuctionality. What you should do is either set the Id column to identity = true or set a value on the insert.
I also encourage you to not use AddWithValue method since it can lead you to some undesired problems. You can read more here: https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
That screenshot you took of your table columns design; get back to that, then click the id column, look in the Properties grid for Identity Specification (might need to expand it) and set it to Yes. Set other properties relevant to your needs and save the table.
Borrowed from another SO question:
There are ways to do this from script but they're generally longer/more awkward than using the UI in management studio.
This will (should) change th column so it auto inserts an incrementing number into itself when you insert values for other rows. Someone else has posted an answer as to how to insert values for it yourself but my recommendation to you as a learner is to use auto increment to save the additional needless complication of providing your own primary key values

How to execute Multiple Insert statements in a single query?

I'm making a form where a user answers some questions to make a pricehold. My problem is I can't store the data from the questions into more than one sql table.
I have tried inserting the other table into the sql command (shown below) and I have tried making another sql command that basically says the same thing with a different name but splitting the name and phone number into the first one and the date created and pick up date into the second one but that only runs the first sql command and then stops so data is never stored into the second table
private void AddPhBttn_Click(object sender, RoutedEventArgs e)
{
SqlConnection furniture = new SqlConnection("Data Source=LAPTOP-F4QFMPFD\\MSSQLSERVER1;Initial Catalog=Furniture;Integrated Security=True");
furniture.Open();
SqlCommand add = new SqlCommand("insert into Customers(Name, Phone) PriceHold(DateCreated, PickUpDate) values ('" + nameTxtBox.Text + "', '" + phoneTxtbox.Text + "', '" + dateTxtBox.Text + "', '" + puDateTxtBox.Text + "')", furniture);
int i = add.ExecuteNonQuery();
if (i != 0)
{
MessageBox.Show("saved");
}
else MessageBox.Show("error");
}
As #Caius Jard said, you can't do this with an ad-hoc query.
So what is an option to do so?
Step 1: Create a Stored Procedure in the Database:
CREATE PROCEDURE usp_InsertData
#Name NVARCHAR(200),
#Phone NVARCHAR(100),
#DateCreated Date,
#PickUpDate Date
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Customers(Name, Phone) VALUES (#Name,#Phone)
INSERT INTO PriceHold(DateCreated, PickUpDate) VALUES (#DateCreated,#PickUpDate)
END
Step 2: Call above Stored procedure in C# Code:
private void AddPhBttn_Click(object sender, RoutedEventArgs e)
{
var furniture = new SqlConnection("Data Source=LAPTOP-F4QFMPFD\\MSSQLSERVER1;Initial Catalog=Furniture;Integrated Security=True");
SqlCommand add = new SqlCommand("usp_InsertData", furniture);
add.CommandType = System.Data.CommandType.StoredProcedure;
add.Parameters.AddWithValue("#Name", nameTxtBox.Text);
add.Parameters.AddWithValue("#Phone", phoneTxtbox.Text);
add.Parameters.AddWithValue("#DateCreated", dateTxtBox.Text);
add.Parameters.AddWithValue("#PickUpDate", puDateTxtBox.Text);
furniture.Open();
int i = add.ExecuteNonQuery();
if (i != 0)
{
MessageBox.Show("saved");
}
else
{
MessageBox.Show("error");
}
furniture.Dispose();
}
You can't do this in SQL
INSERT INTO
myfirsttable(column1, column2)
mysecondtable(column3, column4, column5)
VALUES(value1, value2, value3, value4)
It's flat out a syntax error. Only one table may appear in an insert. The number of values inserted must match the number of columns
If you want to insert into two tables, run two separate inserts from your c# code
Finally, have a long read of http://bobby-tables.com - your code is currently highly insecure and while this may not matter right now because it's just some small test app, it is best to avoid embarking on a learning path that includes coding in this way. As a recruiter I've turned down many job candidates who have written SQL like this and I'd never employ someone who demonstrated this style to me
When working with data in more than one table, if you want to ensure either all insert/update/delete complete successfully or none of them are applied on your data to ensure data integrity, use transactions. I think SqlTransaction is what you're after. Read about it here.
For your specific case, this is one possibility:
private void AddPhBttn_Click(object sender, RoutedEventArgs e)
{
// Necessary input validation to collect and data from input fields. Good practice to avoid SQL injection.
AddFurniture(nameTxtBox.Text, phoneTxtbox.Text, dateTxtBox.Text, puDateTxtBox.Text);
}
private void AddFurniture(string name, string phoneNumber, string createdDate, string pickupDate)
{
string connectionString = "Data Source=LAPTOP-F4QFMPFD\\MSSQLSERVER1;Initial Catalog=Furniture;Integrated Security=True"; // This should ideally come from some configuration.
using(SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction = connection.BeginTransaction("Add Furniture");
command.Connection = connection;
command.Transaction = transaction;
try
{
connection.Open();
command.CommandText = $"insert into Customers (Name, Phone) values ({name}, {phoneNumber});";
command.ExecuteNonQuery();
command.CommandText = $"insert into PriceHold (DateCreated, PickUpDate) values ({createdDate}, {pickupDate});";
command.ExecuteNonQuery();
// Try to commit to database.
// Both the above queries are executed at this point. If any one of them fails, 'transaction' will throw an exception.
transaction.Commit();
}
catch (Exception ex1)
{
// Considering the statements executed using the 'transaction' for this 'connection',
// one of the insert operations have clearly failed.
// Attempt to roll back the change which was applied.
MessageBox.Show($"Insert failed. Trying to roll back {ex1.Message}");
try
{
transaction.RollBack();
}
catch (Exception ex2)
{
// Rollback also failed. Possible data integrity issue. Handle it in your application.
MessageBox.Show($"Roll back failed. {ex2.Message}");
}
}
}
}

DeleteButton code for deleting the data from SQL Server database

I have a form name "AddNewUnitForm" through this I am saving data in a SQL Server database. Please advice code for "DeleteButton" deleting the data from database by selected data of datagridview
SaveButton code is as under for the reference
string connString = ConfigurationManager.ConnectionStrings["dbx"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand("usp_UnitMasterInsertDetails", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
//Parameter
cmd.Parameters.AddWithValue("UNITNAME", AddUnitTextBox.Text);
//Open Connection
conn.Open();
// ExecuteReader (Select Statement)
// ExecuteScalar (Select Statement)
// ExecuteNoQuery (Insert, Update or Delete)
cmd.ExecuteNonQuery();
MessageBox.Show("ADDED SUCCESSFULLY", "Succesful", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
create a stored procedure to delete records
use transactions to if there is a fall back, while deleting
your delete button code will be similar to the insert here you will be calling stored procedure for deleting, with key parameter to pass the stored procedure.
if you want to do soft delete make a column with flag IsDeleted and changes the flag when deleted

ASP.NET Not sure if reading from SQL Server database correctly

I am trying to make a user register page that uploads the user data to a sql server database. I want to have the capability to check if a username already exists and prevent it from being made. I am able to create a new user with first name, last name, username, etc and it updates the database, but it doesn't stop me from creating a user with a username that already exists in the database. Here is my code:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
//connect registration form to database
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["sandboxConnectionStringUserData"].ConnectionString);
conn.Open(); //open connection
//SQL Query
string checkUserName = "select count(*) from UserData where UserName='"+TextBoxUserName.Text+"'";//checks if username is already there
SqlCommand command = new SqlCommand(checkUserName, conn);
int temp = Convert.ToInt32(command.ExecuteScalar().ToString());
if(temp == 1)
{
Response.Write("User name already exists");
}
conn.Close(); //close the database
}
}
I tried debugging and temp's value never changes to 1.
Thanks!
Just add a UNIQUE constraint to the username column and handle the sql exception in your app. Additionally you can/should write an SP that takes username as an argument and checks for existence in the table, and use that in your server-side validation after the form is sorted but before the insert (save()) occurs. That way you reduce the probability of encountering a sql exception but can still deal with it if it occurs.
Your current method of appending the form data to a raw sql query is going to open you up to sql injection. Use a parameterized query instead.
Creating a UNIQUE constraint on the UserName column is a good start. I would also create a stored procedure that checks the existence of the user and inserts or updates as well structure your code a bit more efficiently. The username should be passed in as a parameter and you should properly dispose of the connection object.
As an example your stored procedure may look like:
CREATE PROCEDURE dbo.uspUserData #userName VARCHAR(50)
AS
BEGIN
IF EXISTS(SELECT 1 FROM dbo.UserData WITH(NOLOCK)
WHERE UserName = #userName)
BEGIN
-- update
END
ELSE
BEGIN
-- insert
END
END
And your .NET code may look like:
using (
SqlConnection conn =
new SqlConnection(
ConfigurationManager.ConnectionStrings["sandboxConnectionStringUserData"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("uspUserData", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#UserName", SqlDbType.VarChar).Value = TextBoxUserName.Text;
conn.Open();
cmd.ExecuteNonQuery();
}
}

How to insert date from asp page textbox to sql server

I have a button within my web page to inserts a few values into sql server columns. One of these values happens to be of data type Date. The following is my code for my asp.net page:
protected void Button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd1 = new SqlCommand("insert into dbo.FillTable values ('TextBox2.Text', 'TextBox1.Text', 'FA0005')",con);
SqlDataAdapter dr = new SqlDataAdapter(cmd1);
con.Close();
DataSet dl = new DataSet();
dr.Fill(dl);
//Label5.Text = dl.Tables[0].Rows[1][9].ToString();
}
I want to be able to have the user enter the date in the format (yyyy-MM-dd), which is the date format for my sql server. "TextBox2" is the textbox that holds the date input. Whenever I simply hard code the date as for ex. '2010-01-01', '50', 'FA0005', it works well and inserts the record. However, when I code is as 'TextBox2.Text', 'TextBox1',etc. It gives me an error saying "Conversion failed when converting date and/or time from character string". Can someone help me with this? Its confusing me because having the date in 'yyyy-mm-dd' format works well, which is same as the textbox.
protected void Button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd1 = new SqlCommand(string.Format("insert into dbo.FillTable values ('{0}', '{1}', 'FA0005')", TextBox2.Text, TextBox1.Text), con);
SqlDataAdapter dr = new SqlDataAdapter(cmd1);
con.Close();
DataSet dl = new DataSet();
dr.Fill(dl);
}
Now, let's break down the string.Format function. It says that if I have a string to format like this "Hello {0}!", anything I pass in at the zero index of the function will replace every occurrance of {0}. So, let's say I have this string "Hello {0}, and I say again hello {0}!" and I used it like this string.Format("Hello {0}, and I say again hello {0}!", "world"), I would get a string like this "Hello **world**, and I say again hello **world**!".
Note
However, the above solution leaves you open to SQL Injection, so if you want to protect against that then let's go this route.
protected void Button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd1 = new SqlCommand("insert into dbo.FillTable values (#TextBox2Val, #TextBox1Val, 'FA0005')", con);
cmd1.AddParameterWithValue( "TextBox1Val", TextBox1.Text );
cmd1.AddParameterWithValue( "TextBox2Val", TextBox2.Text );
SqlDataAdapter dr = new SqlDataAdapter(cmd1);
con.Close();
DataSet dl = new DataSet();
dr.Fill(dl);
}
Now let's break this down. The statement sent to the SQL server is just what you see, with the #paramname in the string. But, it will send it as a prepare and prepare that statement with the values you provided in the AddParameterWithValue method. Note that here, as long as the value in the TextBox2.Text is a date you don't have to concern yourself with the format because SQL server will take care of that. Bear in mind that SQL server stores it in one format and you'll display it in another but it can convert from a myriad of formats as long as they are valid.
Now, as stated by #Willem, it would behoove you to ensure that the value in TextBox2.Text is in fact a date, so let's do that, add this snippet at the top of the function ...
DateTime theDate;
if (!DateTime.TryParse(TextBox2.Text, out theDate))
{
// throw some kind of error here or handle it with a default value
...
}
... and then modify the line with the AddParameterWithValue like this ...
cmd1.AddParameterWithValue( "TextBox2Val", theDate );
You don't quite have the mechanism of getting the text box values into the insert correct. Additionally this style of database insertion leaves you vulnerable to SQL Injection attacks. One better option would be to parameterize your SqlCommand, as follows:
SqlCommand cmd1 = new SqlCommand("insert into dbo.FillTable values (#Date1, #Date2, #SomeString)",con);
Then, you can specify parameters as follows:
cmd1.Parameters.AddWithValue("#Date1",TextBox1.Text);
cmd1.Parameters.AddWithValue("#Date2",TextBox2.Text);
cmd1.Parameters.AddWithValue("#SomeString,"FA0005");
Specifying parameters eliminates the SQL Injection risk, and also provides a clean mechanism for getting the values from your text boxes to your INSERT. Hope this helps.
You're inputting the text "TextBox2.Text" into the database, not the value of the textbox. Remove the quotes from TextBox2.Text:
SqlCommand cmd1 = new SqlCommand("insert into dbo.FillTable values
('" + TextBox2.Text + "', '" + TextBox1.Text + "', 'FA0005')",con);
As noted above, you're leaving yourself open to SQL Injection when you're appending strings like this.

Categories

Resources