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.
Related
I'm trying to add new record to trans_daily table, however, the code snippet below executed on button click doesn't work.
THE PROBLEMATIC CODE
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection connection = new SqlConnection(conString);
connection.Open();
string strcom = "INSERT INTO trans_daily (retail_id, cust_name, quantity, " +
"price, date, visibility, remarks_id) VALUES (#RetailID, #CustomerName, " +
"#Quantity, #Price, #Date, #Visibility, #RemarksID)";
SqlCommand cmd = new SqlCommand(strcom, connection);
cmd.Parameters.AddWithValue("#RetailID", ddRetailType.SelectedValue);
cmd.Parameters.AddWithValue("#CustomerName", tbCustomer.Text);
cmd.Parameters.AddWithValue("#Quantity", float.Parse(tbQuantity.Text));
cmd.Parameters.AddWithValue("#Price", float.Parse(tbPrice.Text));
cmd.Parameters.AddWithValue("#Date", DateTime.Now);
cmd.Parameters.AddWithValue("#Visibility", 1);
cmd.Parameters.AddWithValue("#RemarksID", 1);
cmd.ExecuteNonQuery();
}
catch (Exception err)
{
Console.WriteLine(err.Message);
}
}
The following are the data types:
retail_id (int)
cust_name (varchar50)
quantity (float)
price (float)
date (datetime)
visibility (int)
remarks_id (int)
It's also worth to point out that no exception is being thrown.
What could have gone wrong?
THE WORKING CODE
In a separate function, I was able to pull out data from retail table on form load and placed the pulled out data to a dropdown list.
private void formAddTransaction_Load(object sender, EventArgs e)
{
try
{
objConnect = new DatabaseConnection();
conString = Properties.Settings.Default.MVGasConnectionString;
objConnect.Sql = "SELECT * FROM retail";
objConnect.connection_string = conString;
ds = objConnect.GetConnection;
MaxRows = ds.Tables[0].Rows.Count;
FillRetailTypes(conString);
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
}
public void FillRetailTypes(string constring)
{
ddRetailType.DataSource = ds.Tables[0];
ddRetailType.ValueMember = "id";
ddRetailType.DisplayMember = "type";
}
Try this code and you may find your error:
try
{
using(SqlConnection connection = new SqlConnection(conString))
using(SqlCommand cmd = new SqlCommand())
{
connection.Open();
string strcom = "INSERT INTO trans_daily ([retail_id], [cust_name], [quantity], " +
"[price], [date], [visibility], [remarks_id]) VALUES (#RetailID, #CustomerName, " +
"#Quantity, #Price, #Date, #Visibility, #RemarksID)";
cmd.CommandText = strcom;
cmd.Connection = connection;
cmd.Parameters.AddWithValue("#RetailID", SqlDbType.Int);
cmd.Parameter["#RetailID"].Value = ddRetailType.SelectedValue;
cmd.Parameters.AddWithValue("#CustomerName", SqlDbType.VarChar);
cmd.Parameter["#CustomerName"].Value = tbCustomer.Text;
cmd.Parameters.AddWithValue("#Quantity", SqlDbType.Float);
cmd.Parameter["#Quantity"].Value = float.Parse(tbQuantity.Text);
cmd.Parameters.AddWithValue("#Price", SqlDbType.Float);
cmd.Paramter["#Price"].Value = float.Parse(tbPrice.Text);
cmd.Parameters.AddWithValue("#Date", SqlDbType.DateTime);
cmd.Parameter["#Date"].Value = DateTime.Now;
cmd.Parameters.AddWithValue("#Visibility", SqlDbType.Int);
cmd.Parameter["#Visibility"].Value = 1;
cmd.Parameters.AddWithValue("#RemarksID", SqlDbType.Int);
cmd.Parameter["#RemarksID"].Value = 1;
int affectedRows = cmd.ExecuteNonQuery();
Console.WriteLine("You have inserted {0} rows", affectedRows);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
This code will...
... automatically open and close your database connection and command object
... log the amount of affected rows in the database to the console
... log exception messages to the console. You may add a breakpoint to this line if you want to see the whole exception (if one occures)
As explained in this blog, it seems like the problem is in the connection string.
Inside the project folder, 2 .mdf files were created: one is found at the root of the folder (let's call it mdf_1) and the other is inside the bin\Debug folder (let's call it mdf_2).
Now, taking a look inside the Visual Studio (VS) editor, there are 2 .mdf files shown: one under the Server Explorer, and another under the Solution Explorer. Not taking note of the location (from the properties section) of these .mdf files made me think these 2 .mdf files were the same. The thing is, the one under the Server Explorer is mdf_1 while mdf_2 is the one under the Solution Explorer.
VS has a behavior that copies mdf_1 and overwrites mdf_2 everytime the program is run (because by default, .mdf is set to Copy always mdf_1 to mdf_2). My connection string was pointing to the mdf_2 which explains why despite cmd.ExecuteNonQuery() command returns 1, my successfully inserted records are always erased because of the behavior VS has. And since it is mdf_1 that is under Server Explorer, I could not verify the changes in DB. Simply put, I was making changes in mdf_2 while trying to look for the changes in mdf_1.
So to avoid this, I modified my connection string by changing the relative path |DataDirectory| in the connection string to the absolute path of mdf_1 so that no matter how often VS overwrites mdf_2, the changes I make during runtime in mdf_1 aren't overwritten. This was, changes are also reflected in the Server Explorer (where I verify if changes were actually made).
tl;dr : I was updating the .mdf file under bin\Debug folder during runtime while physically looking for the updates in the .mdf file located in the root of the project.
I have a very basic program I'm writing to get used to using visual studio. The main window of the program contains a listbox named listBox1, and a rich text box named richTextBox1, as well as several buttons which perform various actions to get data from the table named DocStorage, which has a column named DocumentName that stores any words from richTextBox1 as a new row in the database.
I have managed to get the save feature to work, it takes any text from the richTextBox1 and stores in the database as a row, no problem.
Now I need to code for the DELETE and OPEN buttons. The DELETE button should remove a record from the SQL Server database, which is simple enough, but I can't figure out how to make it based on which item is selected from the listBox1 before the user pushes the DELETE button named BtnDelete.
I also would like to be able to work in reverse and OPEN that stored string back to the richTextBox1 based on which item the user has selected in listBox1 before they push the OPEN button named BtnOpen.
Trying to implement similar examples from the web has proven unsuccessful after many attempts, would appreciate some guidance in the right direction, so I can learn where I'm going wrong with coding these buttons.
I'm a beginner, so please forgive my ignorance and help me get these final two buttons of my first app completed!
Here is a snippet of my code for BtnDelete_Click
if (MessageBow.Show("Are you sure you want to Delete this File?", "Open File", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
con.Open();
SqlConnection con = new SqlConnection(#"...........");
SqlCommand cmd = new SqlCommand("DELETE [DocumentName] from DocStorage where DocumentName=#DocShred", con);
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("#DocShred", listBox1.SelectedItem.ToString());
con.Close();
MessageBox.Show("Delete Successful", "File Deleted", MessageBoxButtons.Ok);
}
Thanks in advance.
You're on the right track - just not quite there yet....
Several things:
first, you open the con.Open() and in the next line you create it again - from scratch - that doesn't make any sense.....
you're never executing the query - you're building it up, adding parameter value and all - but you're never actually running the code!
You should use using(....) { .... } blocks to ensure proper disposal of your resources
Try this code:
if (MessageBow.Show("Are you sure you want to Delete this File?", "Open File", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
// define connection string (load from config) and query statement
string connStr = ".......";
string qryDelete = "DELETE [DocumentName] FROM DocStorage WHERE DocumentName = #DocShred";
// set up the connection and command
using (SqlConnection con = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(qryDelete, con))
{
cmd.Parameters.Add(new SqlParameter("#DocShred", listBox1.SelectedItem.ToString());
// open connection, execute query, close connection
con.Open();
int rowsAffected = cmd.ExecuteNonQuery();
con.Close();
}
MessageBox.Show("Delete Successful", "File Deleted", MessageBoxButtons.Ok);
}
I ran this slightly modified version...
private void BtnDelete_Click(object sender, EventArgs e)
{
string TrashedDoc = listBox1.SelectedItem.ToString();
if (MessageBox.Show("Are you sure you want to Delete this File?", "Delete File", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
string connStr = #"...............";
string qryDelete = "DELETE FROM [DocStorage] WHERE DocumentName = #DocShred";
using (SqlConnection con = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(qryDelete, con))
{
cmd.Parameters.Add(new SqlParameter("#DocShred", TrashedDoc));
con.Open();
int rowsAffected = cmd.ExecuteNonQuery();
con.Close();
}
/// if the Delete is successful a message box confirms to user
MessageBox.Show("Delete Successful", "File Deleted", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
and although the codes runs fine, for some reason it is not actually deleting the selected item in the listbox from the database, it just gives a Delete Successful message. Refreshing database confirms that it did not delete anything.
I'm building a user registration page that save user's info into a local database. However I get a SqlException error. Does anyone know what I'm doing wrong here? I'm developing the program in ASP.net and using the local database server.
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["RegisterConnectionString"].ConnectionString);
conn.Open();
string checkUser = "select count(*) from Table where userName = '" + txtUN.Text + "'";
SqlCommand comm = new SqlCommand(checkUser, conn);
int temp = Convert.ToInt32(comm.ExecuteScalar().ToString());
if (temp == 1)
{
Response.Write("user already exist");
}
conn.Close();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["RegisterConnectionString"].ConnectionString);
conn.Open();
string insertQuery = "insert into Table(UserName, name, Address, e-Mail, IC, phone, password) values(#Uname, #name, #add, #mail, #ic, #phone, #pswrd) ";
SqlCommand comm = new SqlCommand(insertQuery, conn);
comm.Parameters.AddWithValue("#Uname", txtUN.Text);
comm.Parameters.AddWithValue("#name", txtName.Text);
comm.Parameters.AddWithValue("#add", txtAdd.Text);
comm.Parameters.AddWithValue("#mail", txtEmail.Text);
comm.Parameters.AddWithValue("#ic", txtIC.Text);
comm.Parameters.AddWithValue("#phone", txtPhone.Text);
comm.Parameters.AddWithValue("#pswrd", txtPsswrd.Text);
comm.ExecuteNonQuery();
Response.Redirect("Default.aspx");
Response.Write("registration was succesful");
conn.Close();
}
catch(Exception ex)
{
Response.Write("error"+ex.ToString());
}
}
You don't give the details of the exception, (ie: exception.Message and exception.InnerException.Message) but from your code I think you have the classical "Syntax Error Near ...."
This is caused by the presence of a reserved keyword in your query text. This reserved keyword is TABLE. You could fix it enclosing the word in square brackets (or better change the name of the table to somenthing more meaningful)
string checkUser = "select count(*) from [Table] where userName = ...";
A part from this, remember to use always parameterized queries also for simple tasks as looking for logins. Last but not least, storing password in clear text inside the database is a big NO-NO from a security standpoint. Everyone, having access to your database using some kind of administrative tool, could look at the passwords of your users, someone could intercept the network traffic between user pc and database server and see the credentials sent by your application. So, please, search for password hashing on this site to find a more secure approach to this problem
In my C# Winform Application I have written a code to insert record into the "SQL Server Compact 4.0 Database". Also I had debug code line-by-line everything is working fine (without any error) but after insert functionality when I checked my database I found that record is not inserted into the database, I'm strange why it is happening..!
But I think it is happening because, "when I tried to add database in my project I got this error" Following is my code to insert record into the database--
// Retrieve the connection string from the settings file.
string conString = Properties.Settings.Default.snda_dbConnectionString;
//string conString = "Data Source=|DataDirectory|\\db_snda.sdf";
try
{
conString = conString +";Password = test#1;";
// Open the connection using the connection string.
using (SqlCeConnection con = new SqlCeConnection(conString))
{
con.Open();
// Read in all values in the table.
using (SqlCeCommand cmd = new SqlCeCommand("INSERT INTO tbl_user_master" + "(user_id, password, user_type, user_title, first_name, middle_name, last_name, gender, dob, mobile_no, email_id, plant_code, div_code, region_code, reporting_to, releaving_date, created_date)" + " VALUES(#user_id, #password, #user_type, #user_title, #first_name, #middle_name, #last_name, #gender, #dob, #mobile_no, #email_id, #plant_code, #div_code, #region_code, #reporting_to, #releaving_date, #created_date)", con))
{
cmd.Parameters.AddWithValue("#user_title", strTitle);
cmd.Parameters.AddWithValue("#first_name", strFirstName);
cmd.Parameters.AddWithValue("#middle_name", strMiddleName);
cmd.Parameters.AddWithValue("#last_name", strLastName);
cmd.Parameters.AddWithValue("#gender", strGender);
cmd.Parameters.AddWithValue("#user_type", strUserType);
cmd.Parameters.AddWithValue("#plant_code", strPlantCode);
cmd.Parameters.AddWithValue("#div_code", strDivCode);
cmd.Parameters.AddWithValue("#region_code", strRegionCode);
cmd.Parameters.AddWithValue("#reporting_to", strReportingTo);
cmd.Parameters.AddWithValue("#user_id", strUserName);
cmd.Parameters.AddWithValue("#password", Encrypt(strPassword)); //Encrypt(strPassword)
cmd.Parameters.AddWithValue("#email_id", strEmailId);
cmd.Parameters.AddWithValue("#mobile_no", strMobileNo);
cmd.Parameters.AddWithValue("#dob", strDOB);
cmd.Parameters.AddWithValue("#created_date", strCreatedDate);
cmd.Parameters.AddWithValue("#releaving_date", strReleavingDate);
cmd.ExecuteNonQuery();
}
con.Close();
XtraMessageBox.Show("User Created Successfully.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
ResetAfterSubmit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Thank you...!
It is hapening because you mix up databases - the one you check is not the one that is used during insert as likely when you start the debugging of the program a copys created in the output folder - and then discarded when you stop the program.
This is not exactly a rare problem and a good indication of someone not using a search function to find a solution.
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