Creating dBase-file sporadically throws exception - c#

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();
}

Related

Exception thrown whilst inserting data into an access database using the command "insert into"

I'm working on a project for a college course I'm currently on and I'm having some trouble trying to insert data into a database from an application developed in Visual Studio 2017. I've already connected to the database and am able to open it from the application.
The issue arises when I try to enter data into the table. I get a syntax error. Usually this means there an issue with the actual command right? Well i thought about this and created a new database, and another project and got the inert into command working for that one. At this point , a week of trying to get it to work, I'm stuck and desperately need help. Here is the code I'm using to try and add data to the table.
try
{
Form1.DataBaseConnection.Open();
}
catch (Exception E)
{
MessageBox.Show("!!ATTENTION!! - Error accessing database. Please restart the application. ::::" + E.ToString());
Form1.DataBaseConnection.Close();
}
OleDbCommand DataBaseAddEntry = new OleDbCommand();
DataBaseAddEntry.Connection = Form1.DataBaseConnection;
DataBaseAddEntry.CommandText = "insert into Shoe(Size, Type, Name) values('" + int.Parse(TxtBoxSize.Text) + "','" + TxtBoxType.Text + "','" + TxtBoxName.Text + "')";
DataBaseAddEntry.ExecuteNonQuery();
Form1.DataBaseConnection.Close();
RefreshDataGridView();
As a side not, I didn't design the database or create it. I have to work in a team and the database was created by another member. So when I created my own database it worked fine. Could it be something to do with the actual database and not the code?
Try removing the single quotes from the value for Size, as this looks like it should be an int types.
DataBaseAddEntry.CommandText = "insert into Shoe([Size], [Type], [Name]) values(" + int.Parse(TxtBoxSize.Text) + ",'" + TxtBoxType.Text + "','" + TxtBoxName.Text + "')";
Also, as the comment suggests, you should use parameterized SQL and consider wrapping the try block over the whole database operation, and not only the attempt to open.

c# sqlite not loading after reopening program

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?

In visual Studio 2012 .SDF file not replacing (committing) my changes to original file

I have a problem with inserting to my SQL CE Database.
I have wrote some code, then when I needed a DB, I have right clicked on projected, added new item, Local Database, after that it offered me to choose a datamodel - I selected 'dataset'.
This has created a DB for me, under Server Explorer on my left, and same .sdf file is seen on my right, in solution explorer.
I start my application, I run an insert query, it gives me output that insert was successful, I see that .sdf file under root/bin/Debug/db.sdf was just modified, I close my application, but my original database located at /root/db.sdf. If I query DB from Server explorer, I see no changes/inserted rows. Here is the code I use:
First I have tried sever Data Source options, all uncommented ones did not work for me.
//String connectString = #"Data Source=" + '"' + #"C:\Users\Alex\Documents\Visual Studio 2012\Projects\my\my\myDB.sdf;" + '"';
//String connectString = "Data Source:=" + '"' + #"C:\Users\Alex\Documents\Visual Studio 2012\Projects\my\my\my.sdf" + '"';
//String connectString = "Data Source:=C:\\Users\\Alex\\Documents\\Visual Studio 2012\\Projects\\my\\my\\my.sdf";
//String connectString =#"Data Source:=C:\Users\Alex\Documents\Visual Studio 2012\Projects\my\my\myDB.sdf";
String connectString = "Data Source=myDB.sdf";
using (SqlCeConnection connection = new SqlCeConnection(connectString))
{
connection.Open();
String query = "Insert into items (id, title) VALUES ('" + ID + "', '" + title + "');
SqlCeCommand cmd = new SqlCeCommand(string.Format(query), connection);
int result = cmd.ExecuteNonQuery();
}
After closing application I do a right click on the items table, and 'show table data' - no inserts. What am I doing wrong?
Visual studio is probably creating a copy of your original solution item into the bin/Debug sub-folder (on every build). The original file is never touched while executing your code and your changes are possibly discarded the next time you build the application.
So depending on your use-case you either have to open the database in bin/Debug for viwewing the data or change your connection string to use the one located in the root of your project/solution.
You have a copy of the database in your bin/debug folder, that contains correct data - enter a full path to the database file in your connection string to avoid confusion

How to Create Access DB on the fly from contents of MySQL database and save Locally

I have a remote MySQL database for my company's inventory. The inventory database is the master database for all of the locations we subcontract equipment for. Each property has its own inventory, and for quarterly inventory each location needs to take a laptop and a scanner, and scan their inventory, then sync it to the master database.
The problem is that internet access isn't readily available in all locations, so I need to copy the database to a local file. Concurrency isn't an issue because only one client will ever be connected to the database simultaneously, and each location's database is relatively small, composed of basically <1000 rows of 7 columns.
I have gotten as far as creating an Access file on the HD, but I can't really divine from MSDN how to create a file with a specific schema or how to insert the relevant data from my SELECT statement into said database. I'd been looking onto creating a table adapter on the fly and using .NET's built in methods to do the data transfer, but I still can't find how to create an MS Access file with a specific schema programatically. If anyone has encountered such a problem before, I'd appreciate any insight that could be offered. I basically need to copy the results of a SELECT statement into an MS Access database which I will store locally. All the other code I've got in place.
I'm presently using a rather unwieldy query and foreach loop to do my dirty work, but I was hoping for a more elegant solution, perhaps using a data source created on the fly.
ADOX.Catalog cat = new ADOX.Catalog();
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source="+ fileName + ";" + "Jet OLEDB:Engine Type=5");
string conString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";" + "User Id=admin;Password=;";
OleDbConnection con = new OleDbConnection(conString);
con.Open();
//create command to generate database schema
OleDbCommand command = new OleDbCommand();
command.CommandText = #"CREATE TABLE items (
[category] VARCHAR(16) NOT NULL,
[manufacturer] VARCHAR(32) NOT NULL,
[model] VARCHAR(32),
[description] TEXT NOT NULL,
[serial_number] VARCHAR(64),
[barcode] VARCHAR(8) NOT NULL PRIMARY KEY,
[property] VARCHAR(4) NOT NULL,
[present] TINYINT
)";
command.Connection = con;
command.ExecuteNonQuery();
OleDbCommand cmdInsert = new OleDbCommand();
cmdInsert.CommandText = "INSERT INTO items([category],[manufacturer],[model],[description],[serial_number],[barcode],[property],[present]) VALUES (#cat,#man,#mod,#desc,#ser,#bar,#prop,#pres)";
cmdInsert.Connection = con;
foreach (DataRow row in itemsTableAdapter1.GetData())
{
cmdInsert.Parameters.AddWithValue("#cat",row.ItemArray[0].ToString());
cmdInsert.Parameters.AddWithValue("#man", row.ItemArray[1].ToString());
cmdInsert.Parameters.AddWithValue("#mod", row.ItemArray[2].ToString());
cmdInsert.Parameters.AddWithValue("#desc", row.ItemArray[3].ToString());
cmdInsert.Parameters.AddWithValue("#ser", row.ItemArray[4].ToString());
cmdInsert.Parameters.AddWithValue("#bar", row.ItemArray[5].ToString());
cmdInsert.Parameters.AddWithValue("#prop", row.ItemArray[6].ToString());
cmdInsert.Parameters.AddWithValue("#pres", row.ItemArray[7]);
cmdInsert.ExecuteNonQuery();
cmdInsert.Parameters.Clear();
}
con.Close();
cat = null;
I tried to do this previously but found that in order to create a new AccessDB I actually had to copy an existing database with all the tables etc that I required.
Would you be able to use sqlite? It is tiny, stable and libraries are available for most languages. You will be able to create whatever structure you like on the client machine.

C# database file directory

I'm using the windows forms aplication with an ms access database. And i would like to know if there is a way to show the directory of the database file (to save data in it)excpet like this:
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=save.mdb";
OleDbConnection empConnection = new OleDbConnection(conString);
string insertStatement = "INSERT INTO zivila "
+ "([naziv],[kalorij],[beljakovin],[oh],[mascob]) "
+ "VALUES (#naziv,#kalorij,#beljakovin,#oh,#mascob)";
or this:
"Data Source=D:\Simonova aktovka na namizju\matura\test5\save.mdb";
couse if i use the first one the aplication undos the changes i've made when i close it(the aplication)
the second one makes me have to change the path everytime i bring the aplication to another computer(cous the direktory is different of coars)
So... is there another way?
Try this:
Data Source=|DataDirectory|\save.mdb

Categories