Assuming that I call the method below with the right credentials:
private bool Connect(string username, string password)
{
string CONNSTRING = "Provider = MSDAORA; Data Source = ISDQA; User ID = {0}; Password = {1};";
OleDbConnection conn = new OleDbConnection();
string strCon = string.Format(CONNSTRING, username, password);
conn.ConnectionString = strCon;
bool isConnected = false;
try
{
conn.Open();
if (conn.State.ToString() == "Open")
isConnected = true;
}//try
catch (Exception ex)
{
lblErr.Text = "Connection error";
}//catch
finally
{
conn.Close();
}//finally
return isConnected;
}
I have successfully open the connection in my method below:
private bool ValidateUserCode(string usercode)
{
UserAccountDefine def = new UserAccountDefine();
UserAccountService srvc = new UserAccountService();
UserAccountObj obj = new UserAccountObj();
bool returnVal = false;
bool isValid = Connect(def.DB_DUMMY_USERCODE, def.DB_DUMMY_PASSWORD);
if (isValid)
{
obj.SQLQuery = string.Format(def.SQL_LOGIN, usercode.ToLower(), DateTime.Now.ToString("MM/dd/yyy"));
DataTable dt = srvc.Execute(obj, CRUD.READALL);
if (dt.Rows.Count == 1)
{
returnVal = true;
}
}
return returnVal;
}
The question is how can I determine the connection status in ValidateUserCode() method?
How can I close it afterwards?
Note:
I explicitly declare the string variables in UserAccountDefine(); so you don't have to worry about that.
I already tried declaring a new OleDbConnection conn inside the ValidateUserCode() to but the conn.State always returning "Closed".
UPDATE
I have a system with 2-layer security feature. 1st is in application and 2nd is on database. If a user logs in to the application, the username and password is also used to log him/her in to the database. Now, the scenario is when a user forgot his/her password, we can't determine the fullname, email and contact (which are maintained in the database) of the user. I just know his usercode. To determine the contact details, I have to open an active connection using a DUMMY_ACCOUNT.
Note that I never maintain the password inside the database.
First of all, you call Close() in your finally block, which means that at any point in your second method, the connection would be closed. Moreover, even if you don't Close() it,since conn is a local variable in Connect(), when you're back in ValidateUserCode(), the connection is already up for garbage collection, and when it's Dispose()d, it also closes automatically.
I sugges you either make it a member, pass it as an out parameter, return it by the Connect() method (and return null for failure, or something, if you don't like exceptions)..or redesign the code.
private OleDbConnection Connect(string username, string password)
{
string CONNSTRING = "Provider = MSDAORA; Data Source = ISDQA; User ID = {0}; Password = {1};";
OleDbConnection conn = new OleDbConnection();
string strCon = string.Format(CONNSTRING, username, password);
conn.ConnectionString = strCon;
try
{
conn.Open();
if (conn.State.ToString() == "Open")
return conn;
}//try
catch (Exception ex)
{
lblErr.Text = "Connection error";
}//catch
finally
{
//you don't want to close it here
//conn.Close();
}//finally
return null;
}
I am not sure how this information helps you.
I had similar problem while using OLEDB connection for Excel Reading. I didn't knew the answer. So, just I added a global variable for OleDbConnection initialized to null.
In my method, I used to check that null, if not close it and again open it.
if (con != null)
{
con.Close();
con.Dispose();
}
try
{
con = new OleDbConnection(connectionString);
}
catch (Exception ex)
{
MessageBox.Show("oledbConnection = " + ex.Message);
}
try
{
con.Open();
}
catch (Exception ex)
{
MessageBox.Show("connection open = " + ex.Message + "\n");
}
I could able to continue after this. You can try, if it works for you its good!
I'm not sure I follow the question quite right. My answer is based on the premise that you want to open/retrieve a connection, take an action, and close/release the connection afterward.
The code you include does not do that well. Typical DAO code resembles this pseudocode, in my case taken from some boilerplate code I use.
public DataSet FetchDataSet(string sql, IDictionary paramHash) {
var cnn = AcquireConnection();
var rtnDS = new DataSet();
try
{
var cmd = cnn.CreateCommand();
cmd.CommandText = sql;
SetParameters(cmd, paramHash);
IDbDataAdapter ida = new DataAdapter { SelectCommand = cmd };
LogSql(sql, paramHash, "FetchDataSet");
ida.Fill(rtnDS);
}
catch (Exception ex)
{
DebugWriteLn("Failed to get a value from the db.", ex);
throw;
}
finally
{
ReleaseConnection(cnn);
}
return rtnDS;
}
Note that the code above is strictly about communicating with the database. There is no assessment of whether the data is right or wrong. You might have a DAO that is a subclass of the one that contains the above code, and it might do this:
public MyItemType FindSomeValue(long Id)
{
const string sql = #"SELECT something from somewhere where id=:id";
var myParams = new Dictionary<string, long> { { "id", Id } };
var ds = FetchDataSet(sql, myParams);
return (from DataRow row in ds.Tables[0].Rows
select new Item
{
Id = Convert.ToInt64(row["ID"], CultureInfo.InvariantCulture),
Name = row["NAME"].ToString()
}).FirstOrDefault();
}
In fact, the above is pseudocode from a DAO implementation that I've used for years. It makes data access relatively painless. Note that there is some real code behind those methods like SetParameters (30 - 80 lines or so), and I have a bunch of other protected methods like FetchScalar, ExecuteSQL, etc.
Related
My class has a couple of methods going on. The first one is creating a database, that's done. Then, creates stored procedures that is being read from a sql file. then detach that DB. Now it seems that my store procedure query is taking a while to finish and my method to detach is being invoked while the database is busy. So how do I tell if the database is idle. The exception goes "cannot detach the database because it is currently in use"
Methods:
void CreateStoredProcedures(string type)
{
string spLocation = File.ReadAllText("CreateStoredProcedures.sql");
var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd"));
try
{
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(spLocation);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
bool DetachBackup(string type)
{
var conn = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand("", conn);
command.CommandText = #"sys.sp_detach_db '" + type + DateTime.Now.ToString("yyyyMMdd") + "'";
try
{
conn.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
finally
{
if ((conn.State == ConnectionState.Open))
{
conn.Close();
}
}
return true;
}
Click event:
private void btnFullBackup_Click(object sender, EventArgs e)
{
lblStatus.Text = "Starting full backup...";
Execute("FULL");
progressBar.Value = 20;
lblStatus.Text = "Copying tables...";
progressBar.Value = 60;
CopyTables("FULL");
progressBar.Value = 70;
lblStatus.Text = "Creating stored procedures...";
CreateStoredProcedures("FULL");
progressBar.Value = 80;
CheckDBSize(newBackupLocation, "FULL");
progressBar.Value = 100;
MessageBox.Show("Backup was created successfully", "",
MessageBoxButtons.OK, MessageBoxIcon.Information);
lblStatus.Text = "Done";
progressBar.Value = 0;
if (DetachBackup("FULL") == false)
{
DetachBackup("FULL");
}
}
Chances are it's getting hung on its own connection. sp_detach_db's MSDN https://msdn.microsoft.com/en-CA/library/ms188031.aspx has the following suggestion under the section Obtain Exclusive Access:
USE master;
ALTER DATABASE [DBName] SET SINGLE_USER;
You're DetachBackup method will have connect to master, run the ALTER and the sp_detach_db procedure.
You aren't closing the connection in your CreateStoredProcedures method. Put using statements in like I've shown here and it should fix the problem. (Brief using statement explanation from Microsoft.)
Try this code for your methods:
void CreateStoredProcedures(string type)
{
string spLocation = File.ReadAllText("CreateStoredProcedures.sql");
using (var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd")))
{
try
{
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(spLocation);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} // End of using, connection will always close when you reach this point.
}
bool DetachBackup(string type)
{
using (var conn = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(#"sys.sp_detach_db '" + type + DateTime.Now.ToString("yyyyMMdd") + "'", conn);
try
{
conn.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
} // End of using, connection will always close when you reach this point.
return true;
}
You shouldn't think of it as the database being "busy", but the error message uses good verbage: in use. To find out if the database is currently in use, the most accurate way would be to find out if any sessions have any lock in the particular database, by querying sys.dm_tran_locks. Here is a helper function to return a bool whether or not the database is in use:
bool IsDatabaseInUse(string databaseName)
{
using (SqlConnection sqlConnection = new SqlConnection("... your connection string ..."))
using (SqlCommand sqlCmd = new SqlCommand())
{
sqlCmd.Connection = sqlConnection;
sqlCmd.CommandText =
#"select count(*)
from sys.dm_tran_locks
where resource_database_id = db_id(#database_name);";
sqlCmd.Parameters.Add(new SqlParameter("#database_name", SqlDbType.NVarChar, 128)
{
Value = databaseName
});
sqlConnection.Open();
int sessionCount = Convert.ToInt32(sqlCmd.ExecuteScalar());
if (sessionCount > 0)
return true;
else
return false;
}
}
Note: Make sure your initial catalog in your connection string isn't the database you're trying to make "not in use", as that'll put your current session in the context of the database, not allowing that operation to complete
I ran into a problem where passing a connection from a TableAdapter to some methods throws an exception stating the connectionstring isn't initialized. There are quite a few questions on SO with this exception but none were passing the connection and most were because the ConnectionString was null. Weird thing is I used MessageBox.Show(connection.ConnectionString); through out the chain of methods and I receive a valid connection string at every step. This is a somewhat complicated program that is in production but I will try to simplify the code for this question...
This is the postInventoryData method, which takes a DataGridView with inventory items and iterates through it posting them to the inventory. I use a TransactionScope to ensure the changes are safely rolled back in the event of an error. If an item is a kit(an item comprised of other items) I must iterate through those items and remove them from the inventory. The problem occurs when I check whether or not the item is a kit.
public bool postInventoryData(DataGridView dgv)
{
bool successful = true;
TestDataSetTableAdapters.inentoryTrxTableAdapter inventoryTrxAdapter =
new TestDataSetTableAdapters.inentoryTrxTableAdapter();
try
{
using (TransactionScope trxScope = new TransactionScope
(TransactionScopeOption.Required, new System.TimeSpan(0, 15, 0)))
{
MessageBox.Show(inventoryTrxAdapter.Connection.ConnectionString); // <-- Valid ConnectionString
inventoryTrxAdapter.OpenConnection();
for (int i = 0; i < dgv.Rows.Count; i++)
{
//parameter values
string departmentCode = dgv.Rows[i].Cells["Department_Code"].Value.ToString();
string machineCode = dgv.Rows[i].Cells["Machine_Code"].Value.ToString();
string operatorCode = dgv.Rows[i].Cells["Operator_Code"].Value.ToString();
string itemNumber = dgv.Rows[i].Cells["Item_Number"].Value.ToString();
double? qtyProduced = Convert.ToDouble(dgv.Rows[i].Cells["Quantity"].Value.ToString());
bool isKit =
businessLayer.isItemNumberKit
(inventoryTrxAdapter.Connection, itemNumber); // <-- CULPRIT!
// Inserts the item
dailyProductionInsertQty(
departmentCode,
machineCode,
operatorCode,
itemNumber,
isKit,
qtyProduced,
inventoryTrxAdapter,
trxScope);
}
inventoryTrxAdapter.CloseConnection();
trxScope.Complete();
}
}
catch (System.Exception ex)
{
successful = false;
MessageBox.Show(ex.ToString());
}
return successful;
}
The isItemNumberKit method
public bool isItemNumberKit(SqlConnection connection, string itemNumber)
{
bool contains;
MessageBox.Show(connection.ConnectionString); // <-- Valid ConnectionString
DataTable dt = getKit(connection, itemNumber); // <-- CULPRIT!
if (dt.Rows.Count > 0)
{
contains = true;
}
else
{
contains = false;
}
return contains;
}
The getKit method
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString); // <-- Valid ConnectionString
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
using (myConnection)
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
When I execute postInventoryData the program throws an exception with the message, "The connectionstring property has not been initialized." with the line numbers pointing to isItemNumberKit and getKit. As you can see in the code above, I used a MessageBox.Show(connection.ConnectionString) throughout the process and each time I received a valid Connection string. I have created a workaround which stores a cached DataTable containing all the kit items I can run linq statements on. I am not in emergency mode or anything but I thought this to be weird and an opportunity for me to learn. Thanks in advance for any help!
It might be possible that you have 2 app.config files in your solution with 2 different connection strings.
OK, I figured it out and now when I think about it the answer was somewhat obvious. I always use using(){} blocks to ensure connections and similar objects are properly disposed and taken care of after they are used. The solution was to simply remove the using(myConnection){} block from the getKit method like this:
public DataTable getKit(SqlConnection connection, string itemNumber)
{
DataTable dt = new DataTable();
SqlConnection myConnection = connection;
MessageBox.Show(myConnection.ConnectionString);
SqlParameter paramItemNumber = new SqlParameter();
paramItemNumber.ParameterName = "#ItemNumber";
paramItemNumber.Value = itemNumber;
paramItemNumber.SqlDbType = System.Data.SqlDbType.VarChar;
try
{
string sql =
#"SELECT kits.Row_Id,
kits.Kit_Item_Number,
kits.Location_Code
FROM Inventory.dbo.Z_PV_Kits kits
WHERE kits.Kit_Item_Number=#ItemNumber
";
//myConnection.Open();
using (SqlCommand myCommand = new SqlCommand(sql, myConnection))
{
myCommand.Parameters.Add(paramItemNumber);
SqlDataReader reader = myCommand.ExecuteReader();
dt.Load(reader);
}
}
catch (Exception ex)
{
dt = null;
MessageBox.Show(ex.ToString());
}
return dt;
}
This will leave the connection intact but properly dispose of the command. Sorry for the long winded question with a short simple answer. Hope this might help someone someday.
My MySQL connection throws null reference although this code worked well one year ago.
The line where the debugger indicates the exception contains
"connection = new MySqlConnection(connectionString);":
DBConnect MySqlConnection = new DBConnect();
string[] resultArray = MySqlConnection.GetValidUser(
"tbl_user",
tbEmail.Text,
tbPassword.Text
);
//THROWS null reference exception in method 'private bool OpenConnection()'
//A first chance exception of type 'System.ArgumentException' occurred in System.Data.dll
This is my DBConnect class:
class DBConnect
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
public DBConnect()
{
server = "x.x.x.x";
database = "...";
uid = "...";
password = "...";
string connectionString = "SERVER=" + server + ";" +
"DATABASE=" + database + ";" +
"UID=" + uid + ";" +
"PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
}
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Cannot connect to MySQL server.");
break;
case 1045:
MessageBox.Show("Invalid username or password.");
break;
}
return false;
}
}
public string[] GetValidUser(string dbTable, string dbUsername, string dbPassword)
{
string query = "SELECT id,email,password FROM " + dbTable +
" WHERE email='" + dbUsername +
"' AND password='" + dbPassword + "'";
string[] resultArray = new string[3];
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
resultArray[0] = dataReader.GetInt32(0).ToString();
resultArray[1] = dataReader.GetString(1);
resultArray[2] = dataReader.GetString(2);
}
dataReader.Close();
this.CloseConnection();
}
return resultArray;
}
}
The original code for the database class can be found here.
This is not an answer to the NullReferenceException - we're still working through that in the comments; this is feedback for the security parts.
The first thing we can look at is SQL injection; this is very easy to fix - see below (note I've tidied some other things too)
// note: return could be "bool" or some kind of strongly-typed User object
// but I'm not going to change that here
public string[] GetValidUser(string dbUsername, string dbPassword)
{
// no need for the table to be a parameter; the other two should
// be treated as SQL parameters
string query = #"
SELECT id,email,password FROM tbl_user
WHERE email=#email AND password=#password";
string[] resultArray = new string[3];
// note: it isn't clear what you expect to happen if the connection
// doesn't open...
if (this.OpenConnection())
{
try // try+finally ensures that we always close what we open
{
using(MySqlCommand cmd = new MySqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("email", dbUserName);
// I'll talk about this one later...
cmd.Parameters.AddWithValue("password", dbPassword);
using(MySqlDataReader dataReader = cmd.ExecuteReader())
{
if (dataReader.Read()) // no need for "while"
// since only 1 row expected
{
// it would be nice to replace this with some kind of User
// object with named properties to return, but...
resultArray[0] = dataReader.GetInt32(0).ToString();
resultArray[1] = dataReader.GetString(1);
resultArray[2] = dataReader.GetString(2);
if(dataReader.Read())
{ // that smells of trouble!
throw new InvalidOperationException(
"Unexpected duplicate user record!");
}
}
}
}
}
finally
{
this.CloseConnection();
}
}
return resultArray;
}
Now, you might be thinking "that's too much code" - sure; and tools exist to help with that! For example, suppose we did:
public class User {
public int Id {get;set;}
public string Email {get;set;}
public string Password {get;set;} // I'll talk about this later
}
We can then use dapper and LINQ to do all the heavy lifting for us:
public User GetValidUser(string email, string password) {
return connection.Query<User>(#"
SELECT id,email,password FROM tbl_user
WHERE email=#email AND password=#password",
new {email, password} // the parameters - names are implicit
).SingleOrDefault();
}
This does everything you have (including safely opening and closing the connection), but it does it cleanly and safely. If it method returns a null value for the User, it means no match was found. If a non-null User instance is returned - it should contain all the expected values just using name-based conventions (meaning: the property names and column names match).
You might notice that the only code that remains is actually useful code - it isn't boring plumbing. Tools like dapper are your friend; use them.
Finally; passwords. You should never store passwords. Ever. Not even once. Not even encrypted. Never. You should only store hashes of passwords. This means that you can never retrieve them. Instead, you should hash what the user supplies and compare it to the pre-existing hashed value; if the hashes match: that's a pass. This is a complicated area and will require significant changes, but you should do this. This is important. What you have at the moment is insecure.
Among other things, it sounds like you have problems with the connection string - from comments:
While "connection = new MySqlConnection(); connection.ConnectionString = connectionString;" throws an exception the statement "connection = new MySqlConnection();" does not...
The difference here is simply: in the latter you aren't setting the connection string - so it sounds like your connection string is not correctly escaping the values (most likely, the password); you could try:
var cs = new DbConnectionStringBuilder();
cs["SERVER"] = server;
cs["DATABASE"] = database;
cs["UID"] = uid;
cs["PASSWORD"] = password;
var connectionString = cs.ConnectionString;
I have come across a tricky little problem and here and it is to do with opening a SQL Server database
The calling code is
public MainWindow()
{
InitializeComponent();
dbTools = new DataBaseTools();
if (dbTools.DbWorks)
{
label3.Text = "Worked";
}
else
{
label3.Text = "Try Again";
}
label3.AutoSize = true;
}
and the code for connecting to the server is
namespace LeatherCorset
{
public class DataBaseTools
{
private Boolean dbWorks;
private SqlConnection myConn;
public DataBaseTools(){
dbWorks = false;
InitialiseDatabase();
}
private void InitialiseDatabase(){
myConn = new SqlConnection();
String ConnString =
"Server=KEITH\\SQLEXPRESS;Database=Corset;Trusted_Connection=Yes";
myConn.ConnectionString = ConnString;
try{
if (myConn.State == ConnectionState.Open){
dbWorks = true;
}
}catch (SqlException ex) {
dbWorks = false;
}
}
public Boolean DbWorks{
get { return dbWorks; }
set { dbWorks = value; }
}
}
}
When I run the debugger it comes up with connString with having the value of null.
The name of the server is DESKTOP\SQLEXPRESS
The name of the database is Corset
The owner is Desktop\Keith
I am lost at this point in how to get to connect to SQL Server from c#
I would appreciate any advice and help
I don't see where you have opened the connection using Open(). Also, it is better practice here to initialize the SqlConnection with the correct string. Try something like
bool dbWorks = false;
sting cs = "Data Source=KIETH\\SQLEXPRESS;Initial Catalog=Corsit;Trusted_Connection=Yes";
using (SqlConnection conn = new SqlConnection(cs))
{
try
{
conn.Open();
if (conn.State == ConnectionState.Open)
{
dbWorks = true;
}
}
}
I hope this helps.
Can't see how ConnString is null, I think you may be having some debugging issues, that said, try this:
String ConnString = "Server=KEITH\\SQLEXPRESS;Database=Corset;Trusted_Connection=Yes";
using (myConn = new SqlConnection(ConnString)) // This will make sure you actually close the DB
{
myConn.Open(); // You need to open the connection
try
{
if (myConn.State == ConnectionState.Open)
{
dbWorks = true;
}
}
catch (SqlException ex)
{
dbWorks = false;
}
}
I'd also recommend actually taking out the try/catch, because you're hiding an exception that may tell you everything that's going wrong.
I am working on part of my program where I am deleting entry by using provided Entry ID.
As of right now I am deleting any entry specified by user. This works great but, what I am trying to do is to inform user that there is no such ID to delete. Also, I am using textbox TextChanged which let me to check for certain things in user input while user is typing.
Now, how do I check if Entry ID already exists? What should I include in my if statement to do this?
Also, is there a way I could check that by using TextChanged event handler? I'm not sure about that because I know that if I would have opening and closing connection in TextChanged event, then connection would be opened/closed every time user is typing, so I don't think this is a good idea. But how can I avoid this and so I can do this in real time? Perhaps when user stop typing, and then take a second or two to check for entry id?
This is a code of my delete entry window:
public partial class DeleteEntryWindow : Form
{
string user, pass, filePath;
// Initializing MainWindow form.
MainWindow mainWindow;
public DeleteEntryWindow()
{
InitializeComponent();
txtEntryID.TextChanged += new EventHandler(ValidateInput);
}
public DeleteEntryWindow(MainWindow viaParameter,
string user, string pass, string filePath)
: this()
{
mainWindow = viaParameter;
this.user = user;
this.pass = pass;
this.filePath = filePath;
}
private void ValidateInput(object sender, EventArgs e)
{
int intNumber;
if (!string.IsNullOrEmpty(txtEntryID.Text) &&
int.TryParse(txtEntryID.Text, out intNumber) &&
intNumber > 0)
{
lblMessage.Text = "Entry ID is valid.";
lblMessage.ForeColor = Color.Green;
btnDeleteEntry.Enabled = true;
}
else
{
lblMessage.Text = "You must enter Entry ID number!";
lblMessage.ForeColor = Color.IndianRed;
btnDeleteEntry.Enabled = false;
}
}
private void btnDeleteEntry_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show
("Are you sure you want to remove this entry?",
"Information", MessageBoxButtons.YesNo,
MessageBoxIcon.Information);
if (result == DialogResult.Yes)
{
// SQL query which will delete entry by using entry ID.
string sql = "DELETE FROM PersonalData WHERE DataID = " +
txtEntryID.Text;
DeleteData(sql);
lblMessage.Text = "Entry was deleted!";
lblMessage.ForeColor = Color.Green;
}
else
{
// Do nothing.
}
}
private void DeleteData(string sql)
{
HashPhrase hash = new HashPhrase();
string hashShortPass = hash.ShortHash(pass);
// Creating a connection string. Using placeholders make code
// easier to understand.
string connectionString =
#"Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0};
Persist Security Info=False; Jet OLEDB:Database Password={1};";
using (OleDbConnection connection = new OleDbConnection())
{
// Creating command object.
// Using a string formatting let me to insert data into
// place holders I have used earlier.
connection.ConnectionString =
string.Format(connectionString, filePath, hashShortPass);
using (OleDbCommand command = new OleDbCommand(sql, connection))
{
OleDbParameter prmDataID = new OleDbParameter
("#DataID", txtEntryID.Text);
command.Parameters.Add(prmDataID);
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
}
}
}
To check if the ID already exists, you will need to use SQL just as your delete method does. The following may give you a starting point:
private bool DoesIDExist(string ID)
{
string filePath = ""; //TODO
string hashShortPass = ""; //TODO
DataTable temp = new DataTable();
bool result = false;
string connectionString =""; //TODO
using (OleDbConnection connection = new OleDbConnection(ConnectionString))
{
string sql = #"SELECT * FROM PersonalData WHERE DataID = #DataID";
using (OleDbCommand command = new OleDbCommand(sql, connection))
{
command.Parameters.Add(new OleDbParameter("#DataID", ID));
using (OleDbDataAdapter oda = new OleDbDataAdapter(command))
{
try
{
oda.Fill(temp);
if (temp != null && temp.Rows.Count > 0)
result = true; //ID exists
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
}
}
return result;
}