How to avoid entering duplicate values into table through winform? - c#

in my project I have set the client name as primary key and if I enter the same value, I will get exception, now I want to write the validation, i.e if I re enter the primary key value then I should get a message like "Data already exists", Please help me to do that, The code I am using to insert value is:
private void btnInsert_Click(object sender, EventArgs e)
{
if (txtName.Text == string.Empty)
{
MessageBox.Show("Please enter a value to Project Name!");
txtName.Focus();
return;
}
if (txtContactPerson.Text == string.Empty)
{
MessageBox.Show("Please enter a value to Description!");
txtContactPerson.Focus();
return;
}
SqlConnection con = Helper.getconnection();
con.Open();
string commandText = "InsertClient";
SqlCommand cmd = new SqlCommand(commandText, con);
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#ContactPerson", txtContactPerson.Text);
cmd.CommandType = CommandType.StoredProcedure;
MessageBox.Show("Client details are inserted successfully");
txtName.Clear();
txtContactPerson.Clear();
object Name = cmd.ExecuteNonQuery();
con.Close();
BindData();
}

First, you can prevent a duplicate from ever occurring in the table by using a unique index or constraint. An index/constraint can work in concert with the suggestions below. If you only use a unique index and not one of the below solutions, inserting a duplicate record will throw an error and you will need to handle that on the other end.
you could check for the records existence and insert or update manually:
create procedure MyProcedure
(
#Name nvarchar(100),
...
)
as
if not exists (select * from MyTable where Name = #Name)
begin
insert into MyTable (Name,...) values (#Name,...)
end
else
begin
update MyTable
set ...
where Name = #Name
end

I would tend to allow the user to try to enter any superficially valid primary key, If it is a duplicate then there will be an exception that you can catch and display to the user.
The reason for this is you would have to check the database for an existing key so you might as well do this by trying to insert it and handling any errors.
You could probably improve the validation and error handling a lot more, popping up a message box on every individual problem is annoying, better to have a summary with all the problems. Also holding open a database connection while displaying a message box probably isn't advisable either.
private void btnInsert_Click(object sender, EventArgs e)
{
if (txtName.Text == string.Empty)
{
MessageBox.Show("Please enter a value to Project Name!");
txtName.Focus();
return;
}
if (txtContactPerson.Text == string.Empty)
{
MessageBox.Show("Please enter a value to Description!");
txtContactPerson.Focus();
return;
}
SqlConnection con = Helper.getconnection();
con.Open();
string commandText = "InsertClient";
SqlCommand cmd = new SqlCommand(commandText, con);
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#ContactPerson", txtContactPerson.Text);
cmd.CommandType = CommandType.StoredProcedure;
try
{
object Name = cmd.ExecuteNonQuery();
MessageBox.Show("Client details are inserted successfully");
txtName.Clear();
txtContactPerson.Clear();
BindData();
}
catch(Exception ex)
{
//Handle exception, Inform User
}
finally
{
con.Close();
}
}

I understand your requirement, I see that you are asking about using of your own code instead of the exception. You can get it by using the try catch block. Try the following code:
try
{
object Name = cmd.ExecuteNonQuery();
MessageBox.Show("Client details are inserted successfully");
txtName.Clear();
txtContactPerson.Clear();
BindData();
}
catch(Exception ex)
{
//Handle exception, Inform User
}
finally
{
con.Close();
}

I tend to use Entity Framework as it will throw an exception in this case, however I suppose you could run an sql query first to check whether it exists or not, or though there may be a significant performance overhead with that

Related

Connecting to a database and inserting data into a table

I'm attempting to connect to a database and insert data into the pre-existing table. I'm able to connect to the database it seems but am having trouble getting the data to insert into the table. How do I insert
data into a database in visual studio?
I've already learned how to pass parameters and attempted that, but when I run the program I still receive exceptions. I've attached a screenshot of the error when I try and add a new record. I've looked up multiple different syntaxes for the insert statement, but not sure what I am doing wrong. Below I've included three screenshots one is the form itself, the error I receive, and at the bottom the table structure.
Insert Exception
Form
private void btnAccept_Click(object sender, EventArgs e)
{
if (IsValidData())
{
if (addProduct)
{
product = new Product();
this.PutProductData(product);
try
{
SqlConnection sqlConn = new SqlConnection("Data Source= (LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\MMABooks.mdf;Integrated Security=True");
SqlCommand sqlComm = new SqlCommand();
sqlComm = sqlConn.CreateCommand();
sqlComm.CommandText = #"INSERT INTO Products (paramColum) VALUES
(#ProductCode, #Description,
#UnitPrice, #OnHandQuantity)";
sqlComm.Parameters.Add("#ProductCode", SqlDbType.VarChar);
sqlComm.Parameters.Add("#Description", SqlDbType.VarChar);
sqlComm.Parameters.Add("#UnitPrice", SqlDbType.VarChar);
sqlComm.Parameters.Add("#OnHandQuantity", SqlDbType.VarChar);
sqlConn.Open();
sqlComm.ExecuteNonQuery();
sqlConn.Close();
// Add code here to call the AddProduct method of the ProductDB class.
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.GetType().ToString());
}
}
}
}
private void btnAdd_Click(object sender, EventArgs e)
{
frmAddModifyProduct addProductForm = new
frmAddModifyProduct();
addProductForm.addProduct = true;
DialogResult result = addProductForm.ShowDialog();
if (result == DialogResult.OK)
{
product = addProductForm.product;
txtCode.Text = product.Code;
this.DisplayProduct();
}
}
It should enter a record into the Products table. If I get it down for the insert statement, I'll figure out the retrieve, update, and delete.
TableStructure
You need to add the parameter values, something like:
command.Parameters.Add("#LastName", SqlDbType.VarChar, 30).Value = "Smith";
command.Parameters.Add("#GenderCode", SqlDbType.Char, 1).Value = "M";.
Original answer below, but as pointed in comments below, please avoid it, reasons
cmd.Parameters.AddWithValue("#ProductCode", product.Code);
cmd.Parameters.AddWithValue("#Description", product.Description);
In the current code you have just setup the parameters but not passed the value.
EDIT: Based on #MaxSzczurek comments above
Your INSERT INTO columns don't match your VALUES clause.
INSERT INTO Products (paramColumn) should be changed to:
INSERT INTO Products(ProductCode, Description, UnitPrice, OnHandQuantity)

OledbException - Field too small to accept amount of data

I am trying to use OleDb to insert a new record into an Access database using an SQL command into an entity called 'tblThread' (containing discussion posts, if you are wondering); this is done via a button that will take values from two controls (both being textboxes).
Here's the layout if you would like to see: https://gyazo.com/c43abf4ce055ff997b908badb57f549a
However, after clicking on the button 'Submit Discussion', the control that inserts a new record I get an error display:
https://gyazo.com/1dbdb33290649af04f092533560b1d8c
Now here's the code for the Click event of this button:
Please Note:
absDefault._memberType = 'Teacher' (in this scenario)
private void btnCreate_Click(object sender, EventArgs e)
{
OleDbConnection objConnection = new OleDbConnection(absDefault.conString);
OleDbCommand objCommand = new OleDbCommand();
objCommand.Connection = objConnection;
if (MessageBox.Show("[Piltover]: Are you sure you would like to create this thread", "", MessageBoxButtons.YesNo) == DialogResult.No)
{
return; // Does not execute remaining code
}
else if (txtTitle.TextLength == 0)
{
MessageBox.Show("[Piltover]: You have not created a title");
}
else if (mtxtDescription.TextLength == 0)
{
MessageBox.Show("[Piltover]: You have not added description to your thread");
}
else
{
// DBConnection class is only used within this else block and is not needed anywhere else in this form
DataSet ds; DataRow dRow;
DatabaseConnection objConnect = new DatabaseConnection(); // Instantiating an object from DBConnectionClass and checking if an identical title exist is much faster than the OLEDB process (shown within try block below)
objConnect.Connection_String = absDefault.conString;
objConnect.SQL = "SELECT * FROM tblThread"; ds = objConnect.GetConnection;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
dRow = ds.Tables[0].Rows[i];
if (txtTitle.Text.ToUpper() == dRow.ItemArray.GetValue(1).ToString())
{
MessageBox.Show("[Piltover]: Thread already exist with the title name given");
return;
}
}
}
// FIX - test to see if it works
try
{
objConnection.Open();
// Insert new thread record; avoids SQL injection
objCommand.CommandText = String.Format("INSERT INTO tblThread ([Title], [Description], [ID], [Username], [TeacherBool]) VALUES (#title, #desc, #id, #username, #teacherbool)");//, absDefault.newThreadMemberType);
objCommand.Parameters.AddWithValue("#title", txtTitle.Text);
objCommand.Parameters.AddWithValue("#desc", mtxtDescription.Text);
objCommand.Parameters.AddWithValue("id", absDefault._idNumber);
if (absDefault._memberType == "Teacher")
{
currentTeacher = new csTeacher(absDefault._idNumber, "Teacher");
objCommand.Parameters.AddWithValue("#teacherbool", "True");
objCommand.Parameters.AddWithValue("#username", currentTeacher.Username);
}
else // else 'Student'
{
currentStudent = new csStudent(absDefault._idNumber, "Student");
objCommand.Parameters.AddWithValue("#teacherbool", "False");
objCommand.Parameters.AddWithValue("#username", currentStudent.Username);
}
objCommand.ExecuteNonQuery();
MessageBox.Show("[Piltover]: Thread created");
objConnection.Close();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.ToString());
}
}
I am guessing the problem lies in the attribute [Description], although, I have set the data type to long text:
https://gyazo.com/2d99c945a0a0b98a1e48e8abaf043c2f
If you are wondering what contains within my DatabaseConnection class:
http://pastebin.com/RQs6qPEz
What I am confused is, my inputs are within boundaries (being under 255 characters, if that is the problem):
For example, https://gyazo.com/c43abf4ce055ff997b908badb57f549a
As you can see, the 'masked textbox' besides label 'Description' contains values less than 255 characters.
I have tried debugging to try and find a solution/answer.
System.Data.OleDb allows us to use #names for parameters (and their placeholders), but it ignores the names and treats parameters as strictly positional. Therefore the parameters must be declared in the same order that they appear in the command text.
In your command text you specify
... VALUES (#title, #desc, #id, #username, #teacherbool)
but when you create the parameters via AddWithValue you do so in the following order ...
#title
#desc
id
#teacherbool
#username
... which is not the same.
You need to swap the order of declaring the #teacherbool and #username parameters in your if block.

Can't add a row to database after the query is fine

I am trying to add a row into the database but something seems wrong. The connection is okay and the query is fine too but after pressing the button the row isn't added.
con.Open();
SqlCommand cm = new SqlCommand("INSERT INTO Sports (Спорт) VALUES (#Спорт)",con);
cm.Parameters.AddWithValue("#Спорт", tbAddSport.Text);
try
{
int exec = cm.ExecuteNonQuery();
if (exec > 0)
{
MessageBox.Show("Added");
}
else
{
MessageBox.Show("Error");
}
}
catch (Exception ex)
{
MessageBox.Show("Error (ex)");
con.Close();
}
finally
{
con.Close();
clearBoxes();
}
If there is no exception. I see some possible problems.
You don't need to Close connection in catch block. If exception happen the con.Close() in finally will be execute always.
The other problems I can't find any documentation about cyrillic parameter names. It is possible to be not supported.
Try it like this:
SqlCommand cm = new SqlCommand("INSERT INTO Sports (Спорт) VALUES (#Sport)",con);
cm.Parameters.AddWithValue("#Sport", tbAddSport.Text);
It is bad practise to write cyrillic column names in database. Change name to Sport in the Sports Table.
Also are you sure that clearBoxes(); doesn't remove the possible exception.

SQL Log-In System

This is my first time asking a question on StackOverflow, so I apologize in advance if I ask someone improper. I couldn't find anything to help me while researching this for the past few days, so thank you in advance to anyone who tries to help.
I am making a database that allows people to register and log-in. I am using C# in VS2012.
Below is my log-in code and I am running into some trouble when testing. It iterates through everyone in the database and tells me that log-in has failed till it gets to the right user.
private void button1_Click_1(object sender, EventArgs e)
{
try
{
cn.Open();
}
catch (Exception)
{
MessageBox.Show("Did not connect");
}
SqlCommand cmd = new SqlCommand("SELECT * FROM [Users]", cn);
cmd.Connection = cn;
SqlDataReader reader = null;
reader = cmd.ExecuteReader();
while (reader.Read())
{
if (textBox1.Text == (reader["Username"].ToString()) && textBox2.Text == (reader["Password"].ToString()))
{
MessageBox.Show("Logged in");
}
else
{
MessageBox.Show("Login has failed. Please check your Username and Password.");
}
}
cn.Close();
}
As for my registration portion, I'm not sure if it is a VS2012 thing or what, but the information doesn't get saved into the database after I end debug and then go back to debug again.
private void button1_Click_1(object sender, EventArgs e)
{
cn.Open();
SqlCommand cm1 = new SqlCommand("INSERT INTO Users (Username, Password) VALUES (#Username, #Password)", cn);
SqlCommand cm2 = new SqlCommand("INSERT INTO Contact(Name, Address, City, State, PostalCode, Email, PhoneNumber) VALUES(#Name, #Address, #City, #State, #PostalCode, #Email, #PhoneNumber)", cn);
cm1.Parameters.AddWithValue("#Username", textBox1.Text);
cm1.Parameters.AddWithValue("#Password", textBox2.Text);
cm2.Parameters.AddWithValue("#Name", textBox3);
cm2.Parameters.AddWithValue("#Address", textBox4);
cm2.Parameters.AddWithValue("#City", textBox5);
cm2.Parameters.AddWithValue("#State", textBox6);
cm2.Parameters.AddWithValue("#PostalCode", textBox7);
cm2.Parameters.AddWithValue("#Email", textBox8);
cm2.Parameters.AddWithValue("#PhoneNumber", textBox9);
try
{
int affectedRows = cm1.ExecuteNonQuery(); //+cm2.ExecuteNonQuery();
if (affectedRows > 0)
{
MessageBox.Show("Insert Sucsess!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Insert Failed!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
cn.Close();
}
When you have a database file in you project and you build the project, the database file could be copied from the root project folder into the output (bin\debug or bin\release) folder.
This behavior is controlled by the Copy To Output Directory property of the database file.
If you have this property set to Copy Always then, every time you build your project a fresh copy of the database file is copied from the root project folder to the output directory overwriting the one already there and destroying the changes you have made in the previous debug session.
A suggested fix is to change this property to Copy Never or Copy if Newer
See a detailed explanation on MSDN at this page
For the first part of your question you could avoid to loop on every user adding a WHERE clause to your sql text. Just be aware that you should never use string concatenation to build your sql strings, instead you use ALWAYS the parameters. (Why? You avoid Sql Injection and text single quote parsing/doubling)
string sqlText = "SELECT * FROM [Users] WHERE Username = #usr AND [Password] = #psw";
SqlCommand cmd = new SqlCommand(sqlText, cn);
cmd.Parameters.AddWithValue("#usr", textbox1.Text);
cmd.Parameters.AddWithValue("#psw", textbox2.Text);
SqlDataReader reader = cmd.ExecuteReader();
if(reader.HasRows)
// You have found the user....
Another bit of advice. Do not store the passwords in clear text inside your database. Store always an hash of this string and, on search, compute the hash value and search for it instead of a clear password.
In order for you to get this working you will need a WHERE clause in your SELECT. However, I would not recommend to use
SqlCommand cmd = new SqlCommand("SELECT * FROM [Users] WHERE Username='" + textBox1.Text + "'", cn);
because of possible SQL injection.
Please learn how to use Stored Procedures and how to Execute them from your C# code.

Adapt beginner C# SQL Server INSERT example to work with my database

I have read TONS of tutorials, articles and whatever regarding my issue and honestly, due to my lack of experience I can't twist my fingers around this one so I hope some of you guys can help me out :)
I am working on a project (simply to learn how to program so it's probably very basic), but I have this "News" page where I can update and delete data using a GridView.
Now I would like to INSERT something into my database using 3 textboxes and 1 submit button.
I have 3 rows that has to be inserted:
Headline
Date
Content/the news itself.
Which are stored under NyhedTB from the connectionstring: BoligStjernenConnectionString
My query looks like this:
INSERT INTO [NyhedTB] ([NyhedDato], [NyhedTitel], [NyhedTekst])
VALUES (#NyhedDato, #NyhedTitel, #NyhedTekst)
I read on the internet that this code should do the magic for me (I will have to insert my own values ofc.):
static void Insert()
{
try
{
string connectionString =
"server=.;" +
"initial catalog=employee;" +
"user id=sa;" +
"password=sa123";
using (SqlConnection conn =
new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd =
new SqlCommand("INSERT INTO EmployeeDetails VALUES(" +
"#Id, #Name, #Address)", conn))
{
cmd.Parameters.AddWithValue("#Id", 1);
cmd.Parameters.AddWithValue("#Name", "Amal Hashim");
cmd.Parameters.AddWithValue("#Address", "Bangalore");
int rows = cmd.ExecuteNonQuery();
//rows number of record got inserted
}
}
}
catch (SqlException ex)
{
//Log exception
//Display Error message
}
}
I looked at this code and thought it should be easy enough but really, I can't figure it out.
Here is some advice to get you going, learning programming is a lot of
trial and error.
Start off basic, litrally put three textboxes on a form/page and a
button.
Double click the button to go the code-behind and view the buttons
click event.
Paste in the body of code included with your question (everything in the try-catch).
Put a break-point on the Public Void Button_Click line of code and press F11 to
step through the code.
"one thing is having the code-behind working but how to make the buttons and textboxes working is still a misery"*
Put the textbox as the value rather than your hardcoded values:
cmd.Parameters.AddWithValue("#Address", textBox1.Text);
You also should not insert the Id value, instead modify the EmployeeDetails table and set the ID column to in the properties set Identity Specification (IS Identity) = True. Then right click the ID column and set Primary Key.
Post any error messages you encounter here and when you do get get it working, an additional exercise (that will be very valuable for you) would use a database stored procedure rather than ad-hoc SQL, to safe-guard against sql-injection attacks.
I'm assuming you have SQL Server installed and have a 'employee' database with a table called EmployeeDetails.
protected void GvManualShows_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//label lbl = (label)e.Row.FindControl("lblHidden");
if (e.Row.Cells[14].Text == "Y")
{
// CheckBox cb = (CheckBox)e.Row.FindControl("chk");
CheckBox chk = (CheckBox)e.Row.Cells[0].FindControl("chkBox");
chk.Checked = true;
}
}
}
It's fairly simple. You just have to modify the connection string, the query and its parameters:
private void button1_Click(object sender, EventArgs e)
{
try
{
string connectionString =
"server=SQLServer;" + // SQLServer is your SQL server machine
"initial catalog=employee;" + // employee is your database
"user id=sa;" + // sa is the login to connect the database
"password=sa123"; // sa123 is the password of the login
using (SqlConnection conn =
new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(
"INSERT INTO [NyhedTB] ([NyhedDato], [NyhedTitel], [NyhedTekst]) " +
"VALUES (#NyhedDato, #NyhedTitel, #NyhedTekst)", conn))
{
cmd.Parameters.AddWithValue("#NyhedDato", textBoxDate.Text);
cmd.Parameters.AddWithValue("#NyhedTitel", textBoxTitle.Text);
cmd.Parameters.AddWithValue("#NyhedTekst", textBoxBody.Text);
int rows = cmd.ExecuteNonQuery(); // Inserted rows number
}
}
}
catch (SqlException ex)
{
//Log exception
//Display Error message
}
}
I made changed example code with your requirements and added comments, hope it would be a bit clearer for you to understand whats going on:
static void Insert()
{
try
{
string connectionString =
"server=.;" +
"initial catalog=MyDatabaseName;" + //here you write database name where your NyhedTB table is
"user id=sa;" + //user name to connect to database
"password=sa123"; //password
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd =
new SqlCommand("INSERT INTO NyhedTB (NyhedDato, NyhedTitel, NyhedTekst) VALUES (#NyhedDato, #NyhedTitel, #NyhedTekst)", conn))
{
//all "things" in your sql command what beggins with #
//means that it is parameter and you need to pass values for these parameters:
//For #NyhedDato parameter you set text from your textbox
cmd.Parameters.AddWithValue("#NyhedDato", txtDate.Text);
//For #NyhedTitel parameter you set text from title textbox
cmd.Parameters.AddWithValue("#NyhedTitel", txtTitle.Text);
//For #NyhedTekst parameter you set text from content textbox
cmd.Parameters.AddWithValue("#NyhedTekst", txtContent.Text);
//Execute insert command and get how many records was efected, in this case it should be rows = 1 because you inserting just one record
int rows = cmd.ExecuteNonQuery();
}
}
}
catch (SqlException ex)
{
//Log exception
//Display Error message
}
}
P.s. code not tested. And when you say
I have 3 rows that has to be inserted:
Headline
Date
Content/the news itself.
actually you mean you want to insert record with fields

Categories