Correct update statement c# - c#

I'd like to know if my Update SQL statement is correct, because I have a form where I wanna edit some data. But, for any reason, the form doesn't save the updates and nothing happens in db.
This is my code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Data;
public partial class edit : System.Web.UI.Page
{
SqlConnection con = new SqlConnection("Data Source=CASSIA-PC\\SQLEXPRESS;Initial Catalog=clientes;Integrated Security=True");
protected void Page_Load(object sender, EventArgs e)
{
string v = Request.QueryString["id"];
SqlCommand cmd = new SqlCommand("SELECT idCliente, nmCliente, fantasia, cpf, cep, logradouro, numero, complemento, bairro, cidade, estado, telefone, celular, insEstadual, insMunicipal, email, homePage, tbClientes.tpCliente, tbTipoClientes.idTipoCliente, tbTipoClientes.nmTipoCliente FROM tbClientes INNER JOIN tbTipoClientes ON tbClientes.tpCliente = tbTipoClientes.idTipoCliente WHERE idCliente = '" + v + "'", con);
try
{
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read()) {
txtId.Text = reader["idCliente"].ToString();
txtNome.Text = reader["nmCliente"].ToString();
txtFantasia.Text = reader["fantasia"].ToString();
txtCPF.Text = reader["cpf"].ToString();
txtCEP.Text = reader["cep"].ToString();
txtLogradouro.Text = reader["logradouro"].ToString();
txtNumero.Text = reader["numero"].ToString();
txtComplemento.Text = reader["complemento"].ToString();
txtBairro.Text = reader["bairro"].ToString();
txtCidade.Text = reader["cidade"].ToString();
txtEstado.Text = reader["estado"].ToString();
txtTelefone.Text = reader["telefone"].ToString();
txtCelular.Text = reader["celular"].ToString();
txtInscEstadual.Text = reader["insEstadual"].ToString();
txtInscMunicipal.Text = reader["insMunicipal"].ToString();
txtEmail.Text = reader["email"].ToString();
txtSite.Text = reader["homePage"].ToString();
}
}
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
con.Close();
}
}
protected void btnEditar_Click(object sender, EventArgs e)
{
string v = Request.QueryString["id"];
con.Open();
SqlCommand cmd = new SqlCommand("UPDATE tbClientes SET nmCliente = '"+txtNome.Text+"', fantasia = '"+txtFantasia.Text+"', cpf = '"+txtCPF.Text+"', cep = '"+txtCEP.Text+"', logradouro = '"+txtLogradouro.Text+"', numero = '"+txtNumero.Text+"', complemento = '"+txtComplemento.Text+"', bairro = '"+txtBairro.Text+"', cidade = '"+txtCidade.Text+"', estado = '"+txtEstado.Text+"', telefone = '"+txtTelefone.Text+"', celular = '"+txtCelular.Text+ "', insEstadual = '"+txtInscEstadual.Text+"', insMunicipal = '"+txtInscMunicipal.Text+"', email = '"+txtEmail.Text+"', homePage = '"+txtSite.Text+"' WHERE idCliente = '" + v + "'", con);
try
{
cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
con.Close();
}
}
}

I'm pretty sure your problem is:
WHERE idCliente = '" + v + "'"
Because the Client ID is most likely a numeric field in the database you want to treat it as such:
WHERE idCliente = " + v
As Blorgbeard mentions you need to use Parameterised commands to protect against an SQL Injection attack. This will also solve issues such as textboxes containing apostrophes and etc that would also cause your UPDATE to fail.

I agree with Jeremy, also better if you change to parameterized query OR set your query with a label, copy query and test it directly in SQL Server.
string query = "Update..."
Copy query text and test it directly in SQL Server.

Related

Setting up a chart that displays the number of times a dataset record appears in C#

I am trying to create a chart that when, at the push of a button displays a chart that shows the user the number of times a record has appeared in the dataset/table that it is linked to. Please bare in mind that I have little experience with using Charts in Visual Studios/C#.
Currently I am getting this error: Error
This is all the code I have so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.OleDb;
namespace RRAS
{
public partial class formRRAS : Form
{
public OleDbConnection DataConnection = new OleDbConnection();
public formRRAS()
{
InitializeComponent();
}
private void formRRAS_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'database1DataSet.tblReject_test' table. You can move, or remove it, as needed.
this.tblReject_testTableAdapter.Fill(this.database1DataSet.tblReject_test);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnSearch_Click(object sender, EventArgs e)
{
//This creates the String Publisher which grabs the information from the combo box on the form.
//Select and Dataconnection are also defined here.
string Select = "SELECT * FROM tblReject_test";
string DataConnection;
string Department = txtDepartment.Text;
string Start_Date = txtStart.Text;
string End_Date = txtEnd.Text;
string Anatomy = txtAnatomy.Text;
string RFR = cmbRFR.Text;
string Comment = txtComment.Text;
//Select defines what should be loaded on to the dataset.
if (Department != "")
{
Select = Select + " WHERE department_id =" + "'" + Department + "'";
if (Anatomy != "")
{
Select = Select + "AND body_part_examined =" + "'" + Anatomy + "'";
if (Start_Date != "")
{
Select = Select + " AND study_date =" + "'" + Start_Date + "'";
if (End_Date != "")
{
Select = Select + " AND study_date =" + "'" + End_Date + "'";
if (RFR != "")
{
Select = Select + " AND reject_category =" + "'" + RFR + "'";
if(Comment != "")
{
Select = Select + " AND reject_comment =" + "'" + Comment + "'";
}
}
}
}
}
}
else
{
Select = "SELECT * FROM tblReject_test";
}
//DataConnection connects to the database.
string connectiontring= "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\Database1.mdb";
DataConnection = new OleDbConnection(connectiontring);
//The DataAdapter is the code that ensures both the data in the Select and DataConnection strings match.
OleDbDataAdapter rdDataAdapter = new OleDbDataAdapter(Select, DataConnection);
try
{
//It then clears the datagridview and loads the data that has been selected from the DataAdapter.
database1DataSet.tblReject_test.Clear();
rdDataAdapter.Fill(this.database1DataSet.tblReject_test);
}
catch (OleDbException exc)
{
System.Windows.Forms.MessageBox.Show(exc.Message);
}
}
private void btnLoadChart_Click(object sender, EventArgs e)
{
try
{
int count = database1DataSet.Tables["tblReject_test"].Rows.Count;
DataConnection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = DataConnection;
string query = "SELECT * FROM tblReject_test";
command.CommandText = query;
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
charRejections.Series["RFR"].Points.AddXY(reader["reject_category"].ToString(), reader[count].ToString());
}
DataConnection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
}
}
Your code wouldn't compile as you are assigning a string to DataConnection (instance of OleDbConnection).
The correct usage should be as following.
string connectiontring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\Database1.mdb";
DataConnection = new OleDbConnection(connectiontring));
Also, your code doesn't close Database connection in case of exception.
It would be recommended to use the code as shown below. This is taken from MSDN
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
try
{
connection.Open();
Console.WriteLine("DataSource: {0} \nDatabase: {1}",
connection.DataSource, connection.Database);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// The connection is automatically closed when the
// code exits the using block.
}

C# pass a DataRow[] variable from code behind to .netpage

I am trying to pass a protected DataRow[] msgArray; from code-behind to the .net page.
msgArray contains rows from a DB table that I selected, when I do Response.Write(msgArray[0]["comment"]) it outputs correctly what I have stored in the comment column in my DB.
The problem is that I cannot do the same in my .net page when I load the page where I do this:
<asp:Panel ID="commentSection" runat="server">
<%= msgArray[0]["comment"] %>
</asp:Panel>
I get a Object reference not set to an instance of an object.
What am I doing wrong ?
This is my code-behind(.cs) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using MySql.Data.MySqlClient;
namespace Groups
{
public partial class Group : System.Web.UI.Page
{
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataReader reader;
String queryStr;
String gname;
String gtype;
String uname;
DataTable group = new DataTable();
DataTable msg = new DataTable();
protected DataRow[] msgArray;
protected void Page_Load(object sender, EventArgs e)
{
String id = Request.QueryString["id"];
if (id != null)
{
String connString = System.Configuration.ConfigurationManager.ConnectionStrings["GroupsConnString"].ToString();
conn = new MySql.Data.MySqlClient.MySqlConnection(connString);
conn.Open();
queryStr = "SELECT g.*, (SELECT COUNT(id) FROM app_groups.users_groups_leg ugl WHERE ugl.id_group = g.id) as member_count FROM app_groups.groups g WHERE g.id = " + id;
cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn);
group.Load(reader = cmd.ExecuteReader());
var groupArray = group.AsEnumerable().ToArray();
reader.Close();
int member_count = 0;
int.TryParse(groupArray[0]["member_count"].ToString(), out member_count);
Panel grInfo = new Panel();
grInfo.Controls.Add(new LiteralControl("<br/><div class='panel panel-primary'><div class='panel-heading'><h2>" + groupArray[0]["group_name"] + "</h2></div><div class='panel-body'><span>Categorie: <span class='title'>" + groupArray[0]["group_type"] + "</span></span><br/><span class='membrii'>" + (member_count == 1 ? member_count + " membru" : member_count + " membri") + "</span><br/><span>Fondat pe: " + ConvertUnixTimeStamp(groupArray[0]["founded"].ToString()) + "</span><br/></div></div>"));
groupInfo.Controls.Add(grInfo);
conn.Close();
showComments();
}
}
public static DateTime? ConvertUnixTimeStamp(string unixTimeStamp)
{
return new DateTime(1970, 1, 1).AddSeconds(Convert.ToDouble(unixTimeStamp) + 3600*2);
}
public DataRow[] showComments()
{
String id = Request.QueryString["id"];
if (id != null)
{
String connString = System.Configuration.ConfigurationManager.ConnectionStrings["GroupsConnString"].ToString();
conn = new MySql.Data.MySqlClient.MySqlConnection(connString);
conn.Open();
queryStr = "SELECT gc.* FROM app_groups.group_comments gc WHERE gc.id_group = " + id;
cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn);
msg.Load(reader = cmd.ExecuteReader());
msgArray = msg.AsEnumerable().ToArray();
reader.Close();
Response.Write(msgArray[0]["comment"]);
/*Panel grComments = new Panel();
grComments.Controls.Add(new LiteralControl(""));
groupInfo.Controls.Add(grComments);*/
}
return msgArray;
}
}
}
Create a new class dataAccess.cs
using System;
using System.Data;
namespace Groups
{
public class dataAccess
{
public List<string> GetComments()
{
String connString = System.Configuration.ConfigurationManager.ConnectionStrings["GroupsConnString"].ToString();
conn = new MySql.Data.MySqlClient.MySqlConnection(connString);
try
{
MySql.Data.MySqlClient.MySqlDataReader reader;
DataTable msg = new DataTable();
conn.Open();
List<string> comments = new List<string>();
queryStr = "SELECT gc.* FROM app_groups.group_comments gc WHERE gc.id_group = " + id;
cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn);
msg.Load(reader = cmd.ExecuteReader());
foreach(DataRow dr in msg.Rows)
{
comments.Add(dr["comment"]);
}
reader.Close();
return comments;
}
catch (Exception ex)
{
//throw ex;
}
}
}
}
In the ASPX page
<asp:Panel ID="commentSection" runat="server">
<%
var data = Groups.dataAccess.GetComments();
foreach(string c in data)
{
Response.Write("<p>" + c + "</p>");
}
%>
</asp:Panel>
According to ASP.NET Page Life cycle, your method showComments() will be called after the <%= msgArray[0]["comment"] %> part. Hence it won't be available there.
Best way is to have a control like Label in your .aspx page and update the text property from showComments() method.

DataGridView not showing the data after inserting in local database

I have created an app linked to a local database. It works well, but the only problem is that after I press the insert button, data is inserted in db, but it is not showed in the GridView, only after I close and reopen the application. How can I make it show the data right after I press the button which inserts the values? Thanks !
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlServerCe;
using System.IO;
namespace Gradinita
{
public partial class Grupa : Form
{
string nume = "";
List<Label> labels = new List<Label>();
public Grupa(string nume)
{
InitializeComponent();
this.nume = nume;
}
private void Grupa_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'grupeDataSet8.copii' table. You can move, or remove it, as needed.
this.copiiTableAdapter2.Fill(this.grupeDataSet8.copii);
// TODO: This line of code loads data into the 'grupeDataSet7.copii' table. You can move, or remove it, as needed.
this.copiiTableAdapter1.Fill(this.grupeDataSet7.copii);
// TODO: This line of code loads data into the 'grupeDataSet3.copii' table. You can move, or remove it, as needed.
this.copiiTableAdapter.Fill(this.grupeDataSet3.copii);
var connString = (#"Data Source=" + System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)) + #"\Grupe.sdf");
using (var conn = new SqlCeConnection(connString))
{
try
{
conn.Open();
var query = "SELECT * FROM grupe WHERE Nume='" + nume + "'";
var command = new SqlCeCommand(query, conn);
var dataAdapter = new SqlCeDataAdapter(command);
var dataTable = new DataTable();
dataAdapter.Fill(dataTable);
label1.Text = dataTable.Rows[0][0].ToString();
label2.Text = dataTable.Rows[0][1].ToString();
label3.Text = dataTable.Rows[0][2].ToString();
label4.Text = dataTable.Rows[0][3].ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
private void button1_Click(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
label5.Text = ("1");
}
if (checkBox2.Checked)
{
label5.Text = ("0");
}
textBox1.Text = (Convert.ToInt32(textBox5.Text) - Convert.ToInt32(textBox6.Text)).ToString();
var connString = (#"Data Source=" + Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + #"\Grupe.sdf");
using (var conn = new SqlCeConnection(connString))
{
try
{
conn.Open();
var query = "INSERT INTO copii(prezenta, Nume, Prenume, Program, Taxa, Achitat, Diferenta) VALUES('" + label5.Text + "', '" + textBox2.Text.Trim() + "', '" + textBox3.Text.Trim() + "', '" + textBox4.Text.Trim() + "', '" + textBox5.Text.Trim() + "', '"+ textBox6.Text.Trim()+"', '"+ textBox1.Text.Trim() +"');";
MessageBox.Show(query);
var command = new SqlCeCommand(query, conn);
command.ExecuteNonQuery();
dataGridView1.Refresh(); //not working obviously
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
You need to re-query the data and rebind the datatable.
Something like:
dataGridView1.DataSource = SomeDataTableSource;
dataGridView1.DataBind();
I managed to bypass this by re-adding the grid to the control. First, you copy the grid in a variable, then you remove it from the parent control, and then you add the variable to the controls of that control.
var grid = dataGridView1.Parent.Controls["dataGridView1"];
var ctr = dataGridView1.Parent;
ctr.Controls.Remove(dataGridView1);
ctr.Controls.Add(grid);
It's not tested and I might have mistaken some names cause i don't have a VS installed here, but you get the idea. Not the most elegant solution, but it worked for me. You can also try dataGridView1.Refresh() - which it didn't work for me.

How to get a value from a query and compare it with a string?

Here is the schema of my Society Table:
Society(SocietyName, Email, Password, Status)
So basically I'm creating a login page in which user enters Email and password. If there is an email which matches the one in database then it checks that whether status is equal to president or faculty member or Student Affairs Office. Based on that , it redirects to different pages.
Following is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication3 {
public partial class WebForm1 : System.Web.UI.Page {
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataReader reader;
String QueryStr;
String name;
protected void Page_Load(object sender, EventArgs e) { }
protected void clicked(object sender, EventArgs e) {
String ConnString = System.Configuration.ConfigurationManager.ConnectionStrings["Webappconstring"].ToString();
conn = new MySql.Data.MySqlClient.MySqlConnection(ConnString);
conn.Open();
String QueryStr2 = "";
QueryStr = "";
QueryStr = "Select * from the_society_circle.society WHERE Email= '" + Emailtxt.Text + "' And Psswd=' " + passwordtxt.Text + "'";
cmd = new MySql.Data.MySqlClient.MySqlCommand(QueryStr, conn);
reader = cmd.ExecuteReader();
QueryStr2 = "Select Status from the_society_circle.society where Email = '" + QueryStr + "'";
name = "";
while (reader.HasRows && reader.Read()) {
name = reader["Email"].ToString();
}
if ((QueryStr2== "president" || QueryStr2 == "faculty member") && reader.HasRows ) {
Session["Email"] = name;
Response.BufferOutput = true;
Response.Redirect("WebForm2.aspx", true);
} else {
Emailtxt.Text = "invalid user";
}
conn.Close();
}
}
}
The problem is that if statement is never executed and it always prints invalid user.
PS: Im new to web development :D
You set QueryString2 to this value
QueryStr2 = "Select Status from the_society_circle.society where Email = '" + QueryStr + "'";
It can never be one of the values you check for.
As codemonkey already wrote, your condition will never come true.
You do the following: if ((QueryStr2== "president" || Quer... which evaluates to if (("Select Status from the_society_circle.society where Email = '" + QueryStr + "'"== "president" || Quer.... So you're comparing two different strings, which will never succeed.
I tried to refactor your code and came up with this (not tested, wrote from scratch):
First put your database-related code into a separate class (MySqlAccess) and dispose the database objects (put them into using-blocks which invokes Dispose() on leaving the block).
Don't use the user-inputs in your sql query directly. Remember "all input is evil". So better use parameterized-queries.
The reason your comparison failed was that you didn't execute your second query. Now the code executes just one query and returns the status of the user.
So to sum up:
Have SQL Injection and other malicious actions in mind. For example have a look at this article: http://msdn.microsoft.com/en-us/library/ms161953%28v=sql.105%29.aspx
And never store passwords as clear text in your database. That's the next thing you should care about. Edit your database to store the passwords as salted password hashes and just compare the hashes. For a starting point, have look at this article: http://www.codeproject.com/Articles/704865/Salted-Password-Hashing-Doing-it-Right
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MySql;
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
private string _connectionString;
protected void Page_Load(object sender, EventArgs e)
{
_connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Webappconstring"].ToString();
}
protected void Clicked(object sender, EventArgs e)
{
string email = Emailtxt.Text;
string password = passwordtxt.Text;
var mysqlAccess = new MySqlAccess(_connectionString);
string status = mysqlAccess.GetStatus(email, password);
if (status == Constants.Status.PRESIDENT || status == Constants.Status.FACULTY_MEMBER)
{
Session["Email"] = email;
Response.Redirect("WebForm2.aspx", true);
}
else
{
Emailtxt.Text = "invalid user";
}
}
}
internal class MySqlAccess
{
private readonly string _connectionString;
public MySqlAccess(string connectionString)
{
_connectionString = connectionString;
}
public string GetStatus(string email, string password)
{
using (var conn = new MySqlConnection(_connectionString))
{
conn.Open();
string query = "SELECT Status FROM the_society_circle.society WHERE Email=#Email AND Psswd=#Password;";
using (var cmd = new MySqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("#Email", email);
cmd.Parameters.AddWithValue("#Password", password);
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows && reader.Read())
{
return reader["Status"].ToString();
}
}
}
}
return string.Empty;
}
}
internal class Constants
{
internal class Status
{
public const string PRESIDENT = "president";
public const string FACULTY_MEMBER = "faculty member";
}
}
}

Registration allows duplicate user name in Access

I do have a problem in checking username and password in my registration form. When I tend to register the same username and password that's is already in my database(Access), still it allows to register. I just wanna trap it however, I don't know how to that.
What I want to output is that, I want a trap that says "Account Exists, Try Again!" or "Username Exists!"
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.OleDb; using System.Text.RegularExpressions;
namespace Login { public partial class Register : Form {
private OleDbConnection personalConn;
private OleDbCommand oleDbCmd = new OleDbCommand();
private String connParam = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=E:\Majel\Tic Tac Toe\Database\data.accdb";
public Register()
{
personalConn = new OleDbConnection(connParam);
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
personalConn.Open();
oleDbCmd.Connection = personalConn;
if (textBox1.Text != "" && textBox2.Text != "")
{
int temp;
oleDbCmd.CommandText = "INSERT INTO data(Users,Pass) Values('" + this.textBox1.Text.ToString() + "','" + this.textBox2.Text + "');";
temp = oleDbCmd.ExecuteNonQuery();
if (temp > 0)
{
textBox1.Text = null;
textBox2.Text = null;
MessageBox.Show("Registration Success!");
this.Hide();
Form1 frm = new Form1();
frm.Show();
}
personalConn.Close();
}
}
catch (Exception)
{
MessageBox.Show("Invalid!, Duplicate Data.");
}
}
Notes: textBox1= username
textBox2= password Your attention is much highly appreciated. Thank you so much in advance.
Here is code which uses oledbcommand parameters using ? placeholder as mentioned in MSDN Reference. Also I have added using block which should Close opened connection implicitly.
using(OleDbConnection con = new OleDbConnection(connParam))
using(OleDbCommand cmd = new OleDbCommand("select count(*) from data where Users = ?"))
{
con.Open();
cmd.Connection = con;
cmd.Parameters.AddWithValue("#UserName", textBox1.Text);
object objRes = cmd.ExecuteScalar();
if (objRes == null || (int)objRes == 0)
{
cmd.Parameters.Clear();
cmd.CommandText = "INSERT INTO data (Users,Pass) values(?, ?);";
cmd.Parameters.AddWithValue("#Users", textBox1.Text);
cmd.Parameters.AddWithValue("#Pass", textBox2.Text);
int iRes = cmd.ExecuteNonQuery();
if(iRes > 0)
MessageBox.Show("Registration Success!");
}
else
errorProvider2.SetError(textBox1, "This username has been using by another user.");
}
You almost never use data (in this case, a username) as the primary key for a record in a database. Chance are, your access database is set up the same way.
This means that there is nothing at the DBMS layer that will stop this from occurring, short of making the username the primary key (not recommended).
The solution is to perform a SELECT query to get the count of records with that username, and only allow the insert if the count is 0. You might be able to write a trigger to do this for you, and make the DBMS "reject" the insert, but given your (apparent) level with databases, I wouldn't try that at this point.
To get the count:
SELECT Count(*) FROM Users WHERE userName=#userName
A paramaterized query here is crucial to protect against SQL injection.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Text.RegularExpressions;
namespace Login
{
public partial class Register : Form
{
public Register()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if(text1Box1.Text == "" || textBox2.Text == "")
{
MessageBox.Show("Mandatory fields password or user is empty");
retrun; //I'm not sure if this return is need. Remove it if MessageBox "breaks" the execution of the code below.
}
OleDbCommand cmd = new OleDbCommand(#"Select * from Data where User=#User");
cmd.Parameters.AddWithValue("#User", textBox1.Text);
DataSet dst = SqlManager.GetDataSet(cmd, "Data");
if(dst.Tables[0].Rows > 0)
{
MessageBox.Show("User already exist");
return; //again i'm not sure that this return is needed.
}
Insert("Data", "User", textBox1.Text, "Pass", textBox2.Text);
textBox1.Text = null;
textBox2.Text = null;
MessageBox.Show("Registration Success!");
this.Hide();
Form1 frm = new Form1();
frm.Show();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
You need 1 class make it SqlManager.
public class SqlManager
{
private String connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=E:\Majel\Tic Tac Toe\Database\data.accdb";
public static GetOleDbConnection(OleDbCommand cmd)
{
if(cmd.Connection == null)
{
OleDbConnection conn = new OleDbConnection(connectionString);
conn.Open();
cmd.Connection = conn;
return conn;
}
return cmd.Connection;
}
public static int ExecuteNonQuery(SqlCommand cmd)
{
OleDbConnection conn = GetSqlConnection(cmd);
try
{
return cmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static DataSet GetDataSet(SqlCommand cmd)
{
return GetDataSet(cmd, "Table");
}
public static DataSet GetDataSet(SqlCommand cmd, string defaultTable)
{
OleDbConnection conn = GetSqlConnection(cmd);
try
{
DataSet resultDst = new DataSet();
using (OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
adapter.Fill(resultDst, defaultTable);
}
return resultDst;
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
}
Here is another method you can put in the form class:
public virtual void Insert(string TableName, params object[] colValues)
{
if (colValues == null || colValues.Length % 2 != 0)
throw new ArgumentException("Invalid column values passed in. Expects pairs (ColumnName, ColumnValue).");
OleDbCommand cmd = new OleDbCommand("INSERT INTO " + TableName + " ( {0} ) VALUES ( {1} )");
string insertCols = string.Empty;
string insertParams = string.Empty;
for (int i = 0; i < colValues.Length; i += 2)
{
string separator = ", ";
if (i == colValues.Length - 2)
separator = "";
string param = "#P" + i;
insertCols += colValues[i] + separator;
insertParams += param + separator;
cmd.Parameters.AddWithValue(param, colValues[i + 1]);
}
cmd.CommandText = string.Format(cmd.CommandText, insertCols, insertParams);
DA.SqlManager.ExecuteNonQuery(cmd);
}
Like other guys tell you use parameters in this case you will avoid sql injection. Read in wikipedia about it. Also I add some structure for your program, it is not perfect but I should write a lot for more. It is possible to have some typos here, because I wrote the code here. How you make the check, you fetch the data from database for the user which you write in textbox1.Text. If the dataSet have rows that means at the moment there is existing user with this name. If you don't know what is data set read System.Data.
You should learn to write data access in other classes !
Try this with your Existing Code :
oleDbCmd.CommandText = "INSERT INTO data(Users,Pass) Values('" + this.textBox1.Text.ToString() + "','" + this.textBox2.Text + "') SELECT '" + this.textBox1.Text.ToString() + "','" + this.textBox2.Text + "' WHERE NOT EXISTS(SELECT Users,Pass FROM data WHERE Users='" + this.textBox1.Text.ToString() +"');";
temp = oleDbCmd.ExecuteNonQuery();
if (temp > 0)
{
textBox1.Text = null;
textBox2.Text = null;
MessageBox.Show("Registration Success!");
this.Hide();
Form1 frm = new Form1();
frm.Show();
}
else
{
MessageBox.Show("Username is already Present !!!");
}
It returns 0 if the username is already present in data.

Categories

Resources