c# sqlite not loading after reopening program - c#

I have a simple program written in c# and I am using SQLite to save a list of profiles (emails, passwords). Everything works great until I close the program and then reopen it. When I do that the table is empty. This code is located in my form constructor that fires first when the program loads (it's a single form program, very basic). I am using the System.Data.SQLite library. I can see the file in my project folder (bin/debug/..). Can anyone please explain why this information is not being saved and available to read on reopening the program?
SQLiteConnection.CreateFile("MyDatabase.db");
m_dbConnection = new SQLiteConnection("Data Source=MyDatabase.db;Version=3;");
m_dbConnection.Open();
string sql = "CREATE TABLE " + profileTable + " (" + emailCol + " VARCHAR(320), " + passwordCol + " VARCHAR(30))";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
sql = "SELECT * FROM "+profileTable+" order by "+emailCol+" desc";
command = new SQLiteCommand(sql, m_dbConnection);
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
{
emailProfileListBox.Items.Add(reader[emailCol] as String);
}
Here is my INSERT statement that does insert and has been validated.
string sql1 = "INSERT INTO "+profileTable+" ("+emailCol+", "+passwordCol+") VALUES (\'"+from_email_address.Text+"\', \'"+passwordTextBox.Text+"\')";
SQLiteCommand command1 = new SQLiteCommand(sql1, m_dbConnection);
command1.ExecuteNonQuery();

First line, if you create a new file every time it runs the file would be overwritten.
SQLiteConnection.CreateFile("MyDatabase.db");
Wrap the creation statement in an if block instead checking to see if the file exists on disk.
if (!System.IO.File.Exists("MyDatabase.db"))
{
SQLiteConnection.CreateFile("MyDatabase.db");
// continue your creation script here
}
See the documentation
Creates or overwrites a database file in the specified path. This just creates a zero-byte file which SQLite will turn into a database when the file is opened properly. Note that an existing file will be overwritten.
Side notes
You should also wrap your connections and any other instances where the type implements IDisposable in using blocks to ensure that external resources are always released.
You should use parameterized statements for any values you pass to them. So your inserts, updates, and conditions in your selects should use parameters to pass the values.
Never store passwords, not even encrypted ones. Create a one way salted hash of the password instead and store that. There are plenty of existing libraries / code fragements out there that can do this for you.

Could it be because you are creating the table when you rerun the program?

Related

OLEDB commands aren't being saved in access database

I'm working in Windows Forms and trying to use OLEDB to connect to an access .accdb file.
I can SELECT data without issue.
I can execute Insert and Create commands with no error.
But when I check the database afterward the data is not showing.
For example, when I create a new Table, the code will say the table was created and if I try to create the table again without closing the Windows Form it will throw an error saying the table already exists, but if I close and restart the program it will let me create the table once more.
Also, if I look into the Access file I wont see the table.
I've tried multiple tests both with Access open and closed. The Connection String is correct as I have made changes to tables in the Access file and they are reflected in the SELECT queries I've sent.
I suspect there must be a setting in Access I must enable for it to autocommit changes. But I haven't found it.
OleDbConnection conn = new OleDbConnection(#"Provider = Microsoft.ACE.OLEDB.12.0; Data Source =Database2.accdb");
string query = "INSERT INTO [TestTable] ([Test_Name], [Test_Number]) VALUES (?, ?)";
try
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = query;
cmd.Parameters.AddWithValue("Test_Name", list_all_meters[0][0].Name);
cmd.Parameters.AddWithValue("Test_Number", list_all_meters[0][0].Value);
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
MessageBox.Show("An Item has been successfully added", "Caption", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
}catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}
Looks like the issue was I had set the Database "Copy to Output Directory" to Copy Always, which overwrote my changes every time I ran the program. Changing it to Copy if Newer fixed the issue.

How can I display a message if a value already exists in database?

I am currently writing my first .Net & C# application with Visual Studio, and have a need to write generated values to MySQL from the application.
At present, I can write values fine - but I need to be able to check to see if a value exists and display that line if it does exist, otherwise insert new line to table. My connection string is defined at the top of the form.
I have the following defined already, and it writes to the database successfully if no duplicate values exist in the LicenseKey column. If a duplicate exists, it throws an unhandled exception.
private void SaveDetails()
{
// MySQL 'insert' command
string InsertNewLicense = "insert into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values('" +this.textBoxLicenseeName.Text+ "','" +this.textBoxComputerName.Text+ "','" +this.textBoxContactName.Text+ "','" +this.textBoxContactEmail.Text+ "','" +this.textBoxLicenseKey.Text+ "','" +this.textBoxCreationDate.Text+ "');";
//MySQL instance details
MySqlConnection InsertLicenseDetails = new MySqlConnection(LicenseDatabaseConnection);
//MySQL command execution
MySqlCommand InsertCommand = new MySqlCommand(InsertNewLicense, InsertLicenseDetails);
// Handles command outputs.
MySqlDataReader InsertReader;
//Opens connection to run query on database
InsertLicenseDetails.Open();
// Here our query will be executed and data saved into the database.
MessageBox.Show("License Details Saved. Please ensure you have emailed the license to the customer.");
while (InsertReader.Read())
{
}
InsertLicenseDetails.Close();
}
What I want to happen is for a check to be run on the LicenseKey column to see if the value exists, before different actions are taken.
If the value does not exist, I would like to insert the new line to the table (like my existing command does).
If, however, the value does exist, I would like to pop up a form showing the values from the line that the duplicate appears in as a form.
Where would I put in an event handler to read MySQLException values? What exception would I have to respond to for a duplicate value or no database response?
I agree with what the others have said in their comments, you could change the SQL Query to do the check instead of having 2.
IF(SELECT ... WHERE A = B)
RETURN THAT THE VALUE ALREADY EXISTS
ELSE
INSERT NEW VALUE
Also there was a good comment about SQL Injection and parameterized queries. The query string should look a bit more like
INSERT into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values(#LicenseeName, #ComputerName, #ContactName ...);
and your SqlCommand be parameterized
InsertCommand.Paramaters.AddWithValue("#LicenseeName", this.textBoxLicenseeName.Text);
InsertCommand.Paramaters.AddWithValue("#ComputerName", this.textBoxComputerName.Text);
...
That should be a good start to get you going.
After looking at the queries for a while I decided to try a different tack - instead of using a direct check if it's there, I opted to use a count(*) query. When I click the save button on the form, the buttonClick_event calls SaveDetails(), which runs the following:
private void SaveDetails()
{
string InsertNewLicense = "INSERT into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values(#LicenseeName, #ComputerName, #ContactName, #ContactEmail, #LicenseKey, #CreationDate)";
string LicenseExistence = "SELECT COUNT(*) FROM BCOM.LicenseDetails WHERE LicenseKey LIKE #LicenseKey";
MySqlConnection LicenseDetails = new MySqlConnection(LicenseDatabaseConnection);
MySqlCommand InsertCommand = new MySqlCommand(InsertNewLicense, LicenseDetails);
InsertCommand.Parameters.AddWithValue("#LicenseeName", this.textBoxLicenseeName.Text);
InsertCommand.Parameters.AddWithValue("#ComputerName", this.textBoxComputerName.Text);
InsertCommand.Parameters.AddWithValue("#ContactName", this.textBoxContactName.Text);
InsertCommand.Parameters.AddWithValue("#ContactEmail", this.textBoxContactEmail.Text);
InsertCommand.Parameters.AddWithValue("#LicenseKey", this.textBoxLicenseKey.Text);
InsertCommand.Parameters.AddWithValue("#CreationDate", this.textBoxCreationDate.Text);
MySqlCommand QueryCommand = new MySqlCommand(LicenseExistence, LicenseDetails);
QueryCommand.Parameters.AddWithValue("#LicenseKey", this.textBoxLicenseKey.Text);
MySqlDataReader InsertReader;
LicenseDetails.Open();
if ((int)(long)QueryCommand.ExecuteScalar() >0)
{
MessageBox.Show("This license already exists in the database.");
}
else
{
InsertReader = InsertCommand.ExecuteReader();
MessageBox.Show("License Details Saved. Please ensure you have emailed the license to the customer.");
while (InsertReader.Read())
{
}
}
LicenseDetails.Close();
So, if the query against the license keys returns with any results at all (more than 0 rows returned), a messagebox pops up showing that the key already exists. If the resultant number of rows is 0, the insert command gets run.
This was figured out with a look through MySQL command notes, testing with phpMyAdmin, matching against existing projects online, and support from the following:
The SELECT query was figured out with great support from #Seige.
The query was parameterized with help from Seige, following on from the advice of Sani Huttunen. Many thanks to them both.
Changing to the count method was done on the advice of a fellow coder in another community online - a good friend and brilliant coder.

Creating dBase-file sporadically throws exception

I'm having trouble creating dbf-files while exporting shapefile data. Most of the times it works, but sometimes it'll just trow the following error, even though the file doesn't exist yet:
The Microsoft Jet database engine cannot open the file 'C:\Test\258ba2f1-cc05-4a21-a047-ef060c46a3ca\data\tablename.DBF'. It is already opened exclusively by another user, or you need permission to view its data.
The code looks something like this:
using (var dBaseConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + databasePath + ";Extended Properties=dBASE IV;"))
{
var createTableString = "Create Table " + tableName + ".dbf (p_id char(10), answered char(20), mnote char(50), descr char(50), grade char(50))";
var cmd = new OleDbCommand(createTableString, dBaseConnection);
dBaseConnection.Open();
cmd.ExecuteNonQuery();
This only happens when i use Microsoft Jet database engine. Using Visual FoxPro creates an additional column named "_NullFlags" and the dbf-file doesn't work with any GIS-software.
Any ideas?
What you may want to do is to have a "template" table structure always available and never used in production. Then, just copy that template table to whatever your new table name would need to be. Then, you can query and connect and do whatever with that file version. In addition, you can rename the file extension from .DBF to anything, such as YourTable.GISDBF so no other application would even accidentally open it.
However, if that doesn't work for you, you may want to look at another post I answered quite a while back was issues with Jet engine too. In this case, I am using VFP OleDb driver and using ExecScript(). You can write command line statements and then execute them as if it were a program. As far as creating the table, you could always do something like creating a CURSOR, and then copying out to the destination table as "TYPE FOXPLUS" which would put it into an older supported file format which might also be readable by GIS.
string VFPScript = "ExecScript( "
+ "[create cursor C_Tmp ( fld1 i, fld2 c(50), fld3 c(10) )] +chr(13)+chr(10)+ "
+ "[copy to '" + YourFileNameVariable + "' type FoxPlus] ";
// put this script into command object, then execute it...
using (OleDbCommand comm = new OleDbCommand( VFPScript, connection))
{
comm.ExecuteNonQuery();
}

sql statement isnt saving any data into table

Whenever I execute my C# code everything goes well, no compiler errors, nothing.
But when I go to look at my table in the server explorer, nothing was inserted.
Restarted Visual Studio, still nothing.
I went to debug and I looked at the cmd string before it executes ExecuteNonQuery() and the string still is #itmId,... etc. Not sure if that would effect it or not. Any help?
try
{
Item workingItem = mItemList.Items[itemCombo.SelectedIndex - 1] as Item;
SqlCeConnection sc = new SqlCeConnection(SalesTracker.Properties.Settings.Default.salesTrackerConnectionString);
SqlCeCommand cmd = new SqlCeCommand("INSERT INTO Sales VALUES(#itmId, #itmNm,#fstNm, #date,#prft, #commision)", sc);
cmd.Parameters.AddWithValue("#itmId", workingItem.ItemId);
cmd.Parameters.AddWithValue("#itmNm", workingItem.ItemName);
cmd.Parameters.AddWithValue("#fstNm", logedSalesmen.ID);
cmd.Parameters.AddWithValue("#date", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
cmd.Parameters.AddWithValue("#prft", workingItem.Profit);
cmd.Parameters.AddWithValue("#commision", workingItem.Commision);
sc.Open();
cmd.ExecuteNonQuery();
sc.Close();
MessageBox.Show("Save successfull");
this.Close();
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
EDIT:So it is a matter of the temporary debug database being used, i used select count(0) to figure that out. But im not sure what i should use in my connection string to fix it.
The most common error here is actually a deployment thing - i.e. having 2 different database files in play. In particular, commonly the database file you are debugging (etc) against is often the one in "bin/debug" or similar, and gets overwritten every time you build. But the file people often look at to see the change is the one in their project tree.
Make sure you are looking at the right file.
The code looks fine; the fact that the parameters are still parameters is entirely expected and correct. If you want a simple way of validating the insert, then just check
SELECT COUNT(1) FROM Sales
before and after the insert; I expect it will be incrementing.
Also check that you are closing and disposing the connection cleanly (in case this is simply a buffered change that didn't get written before the process terminated). Both sc and cmd are IDisposable, so you should use using really:
using(SqlCeConnection sc = new SqlCeConnection(
SalesTracker.Properties.Settings.Default.salesTrackerConnectionString))
using(SqlCeCommand cmd = new SqlCeCommand(
"INSERT INTO Sales VALUES(#itmId, #itmNm,#fstNm, #date,#prft, #commision)",
sc))
{
cmd.Parameters.AddWithValue("#itmId", workingItem.ItemId);
cmd.Parameters.AddWithValue("#itmNm", workingItem.ItemName);
cmd.Parameters.AddWithValue("#fstNm", logedSalesmen.ID);
cmd.Parameters.AddWithValue("#date",
DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
cmd.Parameters.AddWithValue("#prft", workingItem.Profit);
cmd.Parameters.AddWithValue("#commision", workingItem.Commision);
sc.Open();
cmd.ExecuteNonQuery();
}
You shouldn't convert DateTime.Now to a string - pass it just as DateTime.Now
You should specify the columns in your insert statement: Ie:
INSERT INTO Sales (ItemID,ItemName...) VALUES (#itmID)
You can use SQL Profiler to check what is being passed to the Database.
Visual Studio can sometimes copy SQLCE databases when you don't want it to, when you build your C# project. So, click on the sdf file in the Solution Explorer and select Copy if newer.

How to insert data into a Microsoft Access Database?

I'm trying to insert data into a Microsoft Access Database.
I inserted data into the Access database, but the first and second time are the only times that show the data I inserted. When I rebuild my application, the data I inserted is gone. I don't know where they go and not show. I use C# with the .NET framework to develop. Here's the relevant part of the code:
OleDbConnection con = new OleDbConnection(ConfigurationManager.ConnectionStrings["Constr"].ConnectionString);
OleDbCommand com = new OleDbCommand();
com.Connection = con;
com.CommandText = "Insert into Language(English,Type,Thai) values(#eng,#type,#thai)";
com.Parameters.AddWithValue("#eng", english);
com.Parameters.AddWithValue("#type", type);
com.Parameters.AddWithValue("#thai", thai);
con.Open();
com.ExecuteNonQuery();
I wrote that code, but I think it is strange. It doesn't show any errors or exceptions, but my data is not inserted correctly. Is this the correct way to insert data? If so, why it it not getting inserted?
When I rebuild my application, the data I inserted is gone
I suspect your database is being overwritten when the application is rebuilt.
This can happen, for example, if your application contains an MDB file that is copied to the output directory on build, and is used from the output directory.
I think Language should be a reserve word and you should wrap it in [] brackets.
Also consider wrapping the code in using blocks, like
using (OleDbConnection con = new OleDbConnection(...))
{
using (OleDbCommand com = new OleDbCommand(sqlString, con))
{
//code
}
}
Other than this [possible issue with table name and that you are not closing your connection], I don't see anything wrong with the code.
You define parameters for the query, but I don't see anywhere those parameters are bound to actual data...
Try some simple tests that replace the variables you're passing in as parameters with actual values, so you can isolate the problem:
In other words, replace this:
com.Parameters.AddWithValue("#eng", english);
com.Parameters.AddWithValue("#type", type);
com.Parameters.AddWithValue("#thai", thai);
With something like this:
//I don't know the data types of your fields, so I'm guessing
com.Parameters.AddWithValue("#eng", "Test1");
com.Parameters.AddWithValue("#type", myEnum.Latin);
com.Parameters.AddWithValue("#thai", "Test1a");
If that works, then your problem probably lies with the english, type, and thai variables and you'll want to make sure they're getting the data you think they should be getting.
May be ur connection string not correct you can it by using .udl file
just follow the link
http://www.gotknowhow.com/articles/test-a-database-connection-string-using-notepad
You can also check the code shown below
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Users\\ruby\\Desktop\\screenShots\\ruby.mdb;Persist Security Info=False");
con.Open();
OleDbCommand cmd = new OleDbCommand("insert into raj(Name,Roll) values('XYZ',12);",con);
cmd.ExecuteNonQuery();

Categories