An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: Could not use ''; file already in use
This is where the error points at:
da.Fill(dt);
The database is located at C:\ChattBankMDB.mdb on my computer.
Database: http://puu.sh/hjQj0/d86ede4c00.png
When I press the button1, I would like for the form to follow up and login on the Customer database else a messagebox.show will say failure to login.
Button on form:
public partial class CustLogin : Form
{
OleDbConnection db = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\ChattBankMDB.mdb");
OleDbDataAdapter da = new OleDbDataAdapter();
DataTable dt = new DataTable();
public CustLogin()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
da = new OleDbDataAdapter("Select CustID, CustPassword From Customers", db);
da.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
if (UserText.Text == dt.Rows[i]["CustID"] && PassText.Text == dt.Rows[i]["CustPassword"])
{
WelcomeCust f = new WelcomeCust();
this.Hide();
f.Show();
}
else
{
MessageBox.Show("FAILURE TRY AGAIN");
}
}
}
I've noticed a couple of potential issues:
Database Injection.
Password in plain text.
Utilizing SqlConnection.
A .mdb isn't a SQL database, it is actually a Microsoft Access database. So you'll want to actually use ADO.NET connection. So your code should actually be:
private readonly string dbConnection = ConfigurationManager.ConnectionStrings["..."].ConnectionString;
private const string query = "SELECT * FROM [Example] WHERE ([Id] = #Id);";
public void Example()
{
using(var connection = new OleDbConnection(dbConnection))
using(var command = new OleDbCommand(query, connection))
{
// Apply parameter, open connection, etc.
}
}
You utilize parameters to avoid a sub-query being introduced. As for your password in plain text you should take a look at BCrypt or another library for a Salt / Hash approach.
Then the change to the connection should alleviate your issue.
Your next issue I believe stems from the Fill being before you build your data table.
The database is an Acces database , so you need to use OleDB to connect to it.
Moreover, the query can cause errors.
Replace :
("Select* from Customers where CustID ='" + UserText.Text +"'
and CustPassword =" + PassText.Text + '"', conn)
By :
("Select * from Customers where CustID = '" + UserText.Text + "'
and CustPassword = '" + PassText.Text + "'", conn);
Related
i am building small login form and this issue showed up.
I SQL server connected (i tried couple different connections aswell), table should be right, i don't see any issue in that.
I have tried already couple different SQL connections and new databases and tables.
private void BtnLogin_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=MYDESKTOP\MSSQLSERVER01;Integrated Security=True;Connect Timeout=30;Encrypt=False; TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
SqlDataAdapter sqa = new SqlDataAdapter ("SELECT COUNT (*) from LOGINFORM where USERNAME ='" + txtUsername.Text +"' and PASSWORD = '" + txtPassword.Text + "'", con);
DataTable dt = new DataTable();
sqa.Fill(dt);
if (dt.Rows[0][0].ToString() == "1")
{
this.Hide();
Form2 main = new Form2();
main.Show();
}
else
{
MessageBox.Show("Username/Password is incorrect. Please try again");
}
}
Expection unhandled invalid object name "LOGINFORM"
You need to set your "Initial Catalog" in your connection string. If you don't specify it, then the default database will be "master", which likely does not contain your table "LOGINFORM". Another option is to fully qualify the table name in your query like databasename.owner.tablename.
I am not getting, how to do insert and update of the data in C# WinForms on single button click.
private void save_Click(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "data source=Sai;database=kaur; user id=sa;password=azxc;";
cn.Open();
string gen;
if (radioButton1.Checked == true)
gen = "Male";
else
gen = "Female";
string clas = null;
clas = comboBox1.Text;
string section = null;
section = comboBox2.Text;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "insert into studetail values('" + textBox1.Text + "','" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section + "')";
cmd.Connection = cn;
int n = cmd.ExecuteNonQuery();
if (n > 0)
MessageBox.Show(n + " Row Inserted.");
else
MessageBox.Show("Insertion failed.");
SqlDataAdapter da = new SqlDataAdapter("select * from studetail ", cn);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
You can add a deletion before the insertion:
private void save_Click(object sender, EventArgs e)
{
DeletePerson(id); // add this
SqlConnection cn = new SqlConnection();
...
}
public void DeletePerson(int id)
{
using(SqlConnection connection = new SqlConnection(credentials))
{
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = "delete from studetail where someUniqeIdColumn = " + id;
cmd.ExecuteNonQuery();
}
}
Using responsible to dispose the connection.
Consider using Entity Framework or LINQ to SQL.
You are exposed to SQL injection.
First off the SQL query isn't quite right. It should look something like the following:
INSERT INTO studetail (columnName1, columnName2, ...columnNameN)
VALUES (value1, value2, ...valueN);
Where the column names are the columns where you want data to be inserted, and the values are the data you want inserted into said columns.
You should also be disposing the connection by wrapping the connection within a using statement.
using(var con = new SqlConnection(connectionString))
{
con.Open();
//rest of code that needs a connection here
}
Additionally, you need to be wary of SQL injection. I highly suggest reading this example from the MSDN website. It will give you an example of using an SQL Update and avoiding SQL injection with use of SqlCommand.Paramaters property.
You should also have a Primary Key in your database tables, if you don't already, so you can uniquely identify each record in a table.
To do an update and a save on the same button, you will need to check if a row already exists for the data that is being edited. This when a Primary comes in handy. You will want to check your database to see if a record already exists
SELECT 1 FROM studetail WHERE <Condition>
The WHERE condition will be the way you uniquely identify (a Primary Key) a row in your table. If the rows in the table are uniquely identified, the above SQL statement will return 1 if a value exists, which means you can UPDATE or 0 if no record exists, so you can INSERT
I am trying to log in to a web service from a website. I have an access database with table USERS (id, user, pass, int admin(1 if it is, 0 if it isn't).
In the web service I have this webmethod:
[WebMethod]
public DataSet login(string u, string p)
{
OleDbConnection CNN = null;
OleDbCommand CMD = null;
string sql = "select * from users where username ='" + u + "' and pass='" + p + "' ";
CNN = new OleDbConnection(conn);
CMD = new OleDbCommand(sql, CNN);
CMD.Connection.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(CMD);
DataSet ds = new DataSet();
adapter.Fill(ds, "logged");
CNN.Close();
return ds;
}
And, in the web site I have this code:
protected void Button1_Click(object sender, EventArgs e)
{
db.Service Login = new db.Service();
Login.login(lUser.Text, lPass.Text);
}
So my question is how can I see if the logged user is admin or no ?
I was thinking somehow to read it from the DataSet ds - since it is filled with all the information that I need, but how to do that ?
Thanks,
dnisko
First of all please avoid passing user typed values to the database directly using sql strings. You are open to SQL Injection attacks and it is error prone as well
//Parametrize your following query.
string sql = "select * from users where username ='" + u + "' and pass='" + p + "' ";
Here is an example on how to parametrize OleDbCommand.
Answer to your question:
Your login() method returns a DataSet object, so you need to assign the return vale of login() method to a DataSet.
db.Service Login = new db.Service();
DataSet ds = Login.login(lUser.Text, lPass.Text);
bool isAdmin = false;
//Check if there is a record for the username and password
if(ds.Tables[0].Rows.Count == 1)
{
//now check if user is an admin or not
isAdmin = Convert.ToBoolean(ds.Tables[0].Rows[0]["admin"]);
if(isAdmin)
{
//User is an admin
}
}else{
//User does not exist in the database
}
I currently have a little app sends a lot of different MySQL Queries to the server. My idea was to wrap the connection, the query and the read to a function with only the actual query as a parameter.
Here is what I got:
public static MySqlDataReader mySqlRead(string cmdText)
{
string connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
command.CommandText = cmdText;
try
{
conn.Open();
MySqlDataReader reader = command.ExecuteReader();
return reader;
}
catch (MySqlException)
{
throw;
}
}
I connect and send the query here:
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
MySqlDataReader orRead = ORFunc.mySqlRead("SELECT * FROM orUsers WHERE username = '" + username + "' AND pass = '" + password + "'");
while (orRead.Read())
{
MessageBox.Show(orRead["id"].ToString());
}
}
Works like a charm... BUT, as you can see above, the connection is never closed. When I add the conn.Close() behind the .ExecuteReader() the reader is empty and everything after return is of course useless.
Maybe it's a stupid question but I'm rather new to C# so please be generous, any hint is appreciated.
cheers,
PrimuS
I had a similar problem in JAVA recently, but I think the same will work for you. Essentially, you can create a class that represents a "SqlCall" object (or something). The class would have accessible members including the connection and the results. The ctor for the class would take in your query text.
Then, all you would have to do is create a new instance of that class, run the query in a method in that class (which would set and/or return the results), GET the results, and then when you are done, call close() on your class (which would then have to be coded such that it closes the connection held internally).
Technically, a better way to do this is to EXTEND the connection class itself, but as you are new to C#, I will not go into the details of doing so.
As I was writing the code below, I realized I may have not actually answered your question. But there's no point in backing out now, so here's what I have:
public class SqlCall {
private static connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
private MySqlConnection conn;
private MySqlCommand command;
private MySqlDataReader reader;
public SqlCall(String query) {
conn = new MySqlConnection(connString);
command = conn.CreateCommand();
command.CommandText = query;
}
public MySqlDataReader execute() throws Exception {
conn.Open();
reader = command.ExecuteReader();
return reader;
}
public void close() {
reader.close();
conn.close();
}
}
Your login code would be:
private void btnLogin_Click(object sender, EventArgs e) {
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
SqlCall sqlcall = new SqlCall("SELECT * FROM orUsers WHERE username = '" + username + "' AND pass = '" + password + "'");
try {
MySqlDataReader orRead = sqlcall.execute();
while (orRead.Read())
{
MessageBox.Show(orRead["id"].ToString());
}
sqlcall.close();
} catch (Exception ex) {
// dostuff
}
}
The point is, unless you copy the data into a new datatable at the very beginning, you'll have to keep the connection open.
On a separate note, YOUR CODE IS PRONE TO SQL INJECTION. Don't know what that is? An example: if I said my username was ';DROP TABLE orUsers;--, then your entire user database would be gone. Look into stored procedures if you want a (very healthy) way around this.
You have difficulties because your idea works against the pattern expected by programs that connects to a database in NET Framework.
Usually, in this pattern you have a method that
INITIALIZE/OPEN/USE/CLOSE/DESTROY
the ADO.NET objects connected to the work required to extract or update data
Also your code has a serious problem called Sql Injection (see this famous explanation) because when you concatenate strings to form your command text you have no defense against a malicious user that try to attack your database
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
MySqlParameter p1 = new MySqlParameter("#uname", username);
MySqlParameter p2 = new MySqlParameter("#pass", pass);
string cmdText = "SELECT * FROM orUsers WHERE username = #uname AND pass = #pass"
DataTable dt = ORFunc.GetTable(cmdText, p1, p2);
foreach(DataRow r in dt.Rows)
{
Console.WriteLine(r["ID"].ToString());
}
}
public static DataTable GetTable(string cmdText, params MySqlParameter[] prms)
{
string connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
// This is the INITIALIZE part
using(MySqlConnection conn = new MySqlConnection(connString))
using(MySqlCommand command = new MySqlCommand(cmdText, conn))
{
// OPEN
conn.Open();
DataTable dt = new DataTable();
command.Parameters.AddRange(prms);
// USE
MySqlDataReader reader = command.ExecuteReader();
dt.Load(reader);
return dt;
} // The closing brace of the using statement is the CLOSE/DESTROY part of the pattern
}
Of course this is a generic example and in my real work I don't use very often these generic methods and prefer to write specialized data access code that return the base object needed to the upper layer of code
I am trying to create an application that allows a user to log in using .sdf, there is not much on the internet about this!
Could really do with some pointers.
This is what I currently have but I believe it is a pile of mess as no matter what I type in each text box it will redirect me to Form2 (which is kinda expected). I know I need an if statement somewhere but not sure how to implement:
private void Login_Click(object sender, EventArgs e)
{
using (SqlCeConnection yourConnection = new SqlCeConnection("Data Source=C:\\Users\\Username\\Documents\\Databases\\New Folder\\Login.sdf"))
{
string query = "SELECT * FROM tbl_employees where Username like '" + textBox1.Text + "' AND Password like '" + textBox2.Text +"'";
SqlCeDataAdapter dA = new SqlCeDataAdapter(query, yourConnection);
SqlCeCommandBuilder cBuilder = new SqlCeCommandBuilder(dA);
this.Hide();
Form2 secondForm = new Form2();
secondForm.ShowDialog();
}
}
First, SQL Server CE database i.e .sdf file is just another storage file. It is very very light and portable version of SQL Server.
But, at most, your code and logicwould be similar to the one for SQL Server. Just different classes. i.e SqlCeConnection, SqlCeCommand and so on.
Now you need to verify that your connectionString is correct.
string connectionString ="data source=physical path to .sdf file;
password=pwdThtUSet; persist security info=True";
using (SqlCeConnection yourConnection = new SqlCeConnection(connectionString))
{
....your logic
}
Now, in your query to search for the username and password combination matching row, don't do it with like because you need exact match.
so do it like:
string query = "SELECT * FROM tbl_employees where Username ='" + textBox1.Text + "' AND Password ='" + textBox2.Text +"'";
SqlCeDataAdapter dA = new SqlCeDataAdapter(query, yourConnection);
DataTable dt = new DataTable();
dA.Fill(dt);
if(dt.Rows.Count>0)
{
this.Hide();
Form2 secondForm = new Form2();
secondForm.ShowDialog();
}
Try this only after the login criterion has been met:
if (usernametextbox.Text.Equals("form2username", StringComparison.InvariantCultureIgnoreCase)) {
// code for redirection to form2
Hide();
con.Close();
} else {
if (usernametextbox.Text.Equals("form3username", StringComparison.InvariantCultureIgnoreCase)) {
// code for redirection to form3
Hide();
con.Close();
}
}