Sqlite c# creates 2 same named databases - c#

I have a problem that when i want to create database and specify its name it is created in the specified directory and in directory where the aplication is running. Why is that happening?
Code that creates database:
using System.Data.SQLite;
...
private static string AddDb(string dbName, string dbPassword)
{
try
{
//default paths
string startupPath = Environment.CurrentDirectory;
string dataBasePath = startupPath + "\\DB\\" + dbName;
//creating the dbfile
SQLiteConnection.CreateFile(dataBasePath);
//Opening connection
SQLiteConnection dbConnString;
dbConnString = new SQLiteConnection("Data Source =" + dbName + ";Version=3;");
dbConnString.Open();
dbConnString.ChangePassword(dbPassword);
dbConnString.Close();
return dataBasePath;
}
catch
{
MessageBox.Show("Failed to create database", "DB Creator");
return "";
}
}

The problem seems to be that you use different paths in CreateFile and your connection string.
If you look at your code below you'll notice that in one case you use a full path to create the file (databaseBasePath), while in the other case you only use the database file name in your connection string (dbName). Without an absolute path, this may be a different folder!
string dataBasePath = startupPath + "\\DB\\" + dbName;
SQLiteConnection.CreateFile(dataBasePath);
SQLiteConnection dbConnString;
dbConnString = new SQLiteConnection("Data Source =" + dbName + ";Version=3;");
It seems like Open then creates the file if it can't find it.
A word on the paths:
You're not allowed to write the Program Files folder, so using the current folder for the database file is really a bad idea.
The use of Environment.CurrentDirectory is also a bad idea. Depending on how you start your application, this may or may not be the folder that you think it is (see my comments to the other answers and this).
Never assume that \ is actually the path separator. Use Path.Combine instead.
I suggest that you use Environment.GetFolderPath to get a location that's shared among all users (if the database content should be shared) or private to the current user (if all users should have their own database) and create the database there:
string baseFolder = Environment.GetFolderPath(<wherever it should be>);
string dataBasePath = Path.Combine(baseFolder, "DB", dbName);
SQLiteConnection.CreateFile(dataBasePath);
SQLiteConnection dbConnString = new SQLiteConnection(String.Format("Data Source = {0};Version=3;", dataBasePath);

The Environment.CurrentDirectory contains the directory that the application starts from by default. You can set this property. See the MSDN article Environment.CurrentDirectory Property

Related

How to use a file from streaming assets on android with Unity?

Background information
My game is working on iOS, and now trying to update it to work on android. I have a database, Artifact.db, in a StreamingAssets folder, that is built off of SQLite and that has read-only information that I use to get data for the game.
Issue
The core issue is that the SQlite can't read the data, most likely because its not accessible from what I have been reading through on the docs. I am looking for any solutions but preferably something using the UnityWebRequest feature rather than the deprecated WWW
Working iOS Code
// Platform dependent code
string filepath = Application.streamingAssetsPath + "/Artifact.db";
string conn = "URI=file:" + filepath;
// SQlite
IDbConnection dbconn;
IDbCommand dbcmd;
IDataReader reader;
dbconn = (IDbConnection)new SqliteConnection(conn);
dbconn.Open();
dbcmd = dbconn.CreateCommand();
string sqlQuery = $"SELECT * FROM Artifact WHERE Rarity='{type}'";
dbcmd.CommandText = sqlQuery;
reader = dbcmd.ExecuteReader();
Using this code above on android results in error when doing the reader = dbcmd.ExecuteReader(); since it cannot find file.
Attempts at Android code
(Since the SQLite code itself is fine I'll only be including the platform-dependent section which deals with finding the file.)
string DatabaseName = "Artifact.db";
#if UNITY_ANDROID
string filepath = Application.persistentDataPath + "/Artifact.db";
if (!File.Exists(filepath))
{
Debug.Log("Database not in Persistent path");
// if it doesn't ->
// open StreamingAssets directory and load the db ->
var loadDb = new WWW("jar:file://" + Application.dataPath + "!/assets/" + DatabaseName); // this is the path to your StreamingAssets in android
while (!loadDb.isDone) { } // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
// then save to Application.persistentDataPath
File.WriteAllBytes(filepath, loadDb.bytes);
}
string conn = "URI=file:" + filepath;
#endif
I also tried the code from this unity forum post. (also modified some things to fit my project)
var loadingRequest = UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, "Artifact.db"));
// Used "Artifact.db" instead of "your.bytes"
loadingRequest.SendWebRequest();
while (!loadingRequest.isDone) {
if (loadingRequest.isNetworkError || loadingRequest.isHttpError) {
break;
}
}
if (loadingRequest.isNetworkError || loadingRequest.isHttpError) {
} else {
File.WriteAllBytes(Path.Combine(Application.persistentDataPath , "Artifact.db"), loadingRequest.downloadHandler.data);
// Used "Artifact.db" instead of "your.bytes"
}
string filepath = Application.persistentDataPath + "/Artifact.db";
string conn = "URI=file:" + filepath;
What I am hoping for
I ideally hope to replicate the iOS code. I think this might mean copying the Artifact.db file to somewhere that is persistent and accessible on android and then using that file location to open the file with SQLite.

OleDb connection to Access 2013 database

I have a program that reads from and writes to an Access database. It works fine on my own computer but when I tried to download it on a new computer that has the new Office 2013 programs it said that the provider in connection string didn't work. Here's my connection string:
string filepath = #"C:\FamilyFoundations\ProvidentLiving\App\Data\"; // Hold the path to the file
string dbPath = filepath + "GoalsDB.accdb"; // Holds the name of our data base
// string to create our database
string db = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + dbPath + "; JET OLEDB:Engine Type=5";'
Does my string need to be changed or is there something I need to download on my friends computer? My first thought is that there is a new Microsoft.JET that I need to include, but please correct me if I'm wrong.

Opening Access Database with C#

I have this connection string :
OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=..\Release\DB.accdb"); // Database Connection
I want my program to connect to the database without the "..\Release\" in the string.
What I mean is, that i want the program to look for the database in the program's folder, without specifying the folder's name (whatever the folder's name is).
How is that done?
You should add your DB to the project (Add -> Existing Item...) and set Build Action to Content and Copy to Output Directory to Copy always:
After that you can using following connection string:
string cs = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=test.mdb;Persist Security Info=False;";
Following code, will find database file in program folder or sub-folder:
string programPath = System.IO.Directory.GetParent(System.Reflection.Assembly.GetExecutingAssembly().Location).FullName;
var dbPath = System.IO.Directory.GetFiles(programPath, "*.accdb", SearchOption.AllDirectories).FirstOrDefault();
string cs = null;
if (!string.IsNullOrEmpty(dbPath))
{
cs = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Persist Security Info=False;", dbPath);
}
Perhaps you could use something like
String strAppDir = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
String strFullPathToMyFile = System.IO.Path.Combine(strAppDir, "DB.accdb");
ref:
How to: Get the Application Directory

File upload control error-Access denied used by another person

when upload the same file for the multiple times i am getting this error......
"The process cannot access the file 'd:\MarketingSystem\ExcelImport\Sample.xls' because it is being used by another process."
getting error in this line
RevenueDumpFileUpload.PostedFile.SaveAs(Server.MapPath(strFilePathOnServer) + RevenueDumpFileUpload.FileName);
This is my full code.....
protected void btnImport_Click(object sender, EventArgs e)
{
if (RevenueDumpFileUpload.HasFile)
{
string strFilePathOnServer = ConfigurationManager.AppSettings["RevenueDumpFileLocation"];
String sConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath(strFilePathOnServer) + RevenueDumpFileUpload.FileName + ";Extended Properties=Excel 8.0;";
string strPostedFileName = RevenueDumpFileUpload.PostedFile.FileName;
if (strPostedFileName != string.Empty && RevenueDumpFileUpload.PostedFile.ContentLength != 0)
{
//Delete Old file before uploading new file.
if (System.IO.File.Exists(strFilePathOnServer))
{
System.IO.File.Delete(strFilePathOnServer);
}
//Save-Upload File to server.
RevenueDumpFileUpload.PostedFile.SaveAs(Server.MapPath(strFilePathOnServer) + RevenueDumpFileUpload.FileName);
RevenueDumpFileUpload.FileContent.Dispose();
}
OleDbConnection Exlcon = new OleDbConnection(sConnectionString);
try
{
Exlcon.Open();
}
catch
{
return;
}
finally
{
RevenueDumpFileUpload.PostedFile.InputStream.Flush();
RevenueDumpFileUpload.PostedFile.InputStream.Close();
}
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [Sheet1$]", Exlcon);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
objAdapter1.Fill(objDataset1, "XLData");
methodtosave();
}
}
In my web config file:
<appSettings>
<add key="RevenueDumpFileLocation" value="~/ExcelImport/"/>
How to resolve this?
Help me..
Thanks in advance
Well, if the OleDbConnection acts anything like the SqlConnection object, you've got this line:
Exlcon.Open();
which is opening the connection, but you don't have a matching line to close the connection. Which means the Jet database provider is going to continue to keep this file open until the connection object is garbage collected. It would be far better to wrap this line:
OleDbConnection Exlcon = new OleDbConnection(sConnectionString);
In a using statement, whose body extends over the remainder of the function, so that you're guaranteed that it's closed/disposed.
Next, have you considered what happens if multiple users upload files with the same name simultaneously - this method will be broken. It may be better to use a new file name on the server, related to the user ID or session ID, and wrap a try/finally around the whole method to ensure the file is deleted after use.
The above may be the cause of your current issues, if this is an error coming out of production - if two people attempt an upload at the same time, then both of their requests may go past the "delete if it exists" part of the code, then one request manages to save the file and open a connection, then the other request will fall over when trying to save the same file name.
You forget to pass the File Name and File Extension when you are trying to delete the file.
if (System.IO.File.Exists(Server.MapPath(strFilePathOnServer) + strPostedFileName+
System.IO.Path.GetExtension(RevenueDumpFileUpload.FileName)))
{
System.IO.File.Delete(Server.MapPath(strFilePathOnServer) + strPostedFileName +
System.IO.Path.GetExtension(RevenueDumpFileUpload.FileName) );
}

Accessing folder in console application

I'm trying to write a function to read csv contents into a datatable.
I'm getting an exception about the file path and wondering what it is that I'm doing wrong.
All I did was create the console app and create a folder in the project called 'Data'.
public DataTable ReadCSV(string filename)
{
DataTable dt = new DataTable();
string sql = "SELECT * FROM " + filename;
string path = "Data\\";
string connstring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + filename + ";" + "Extended Properties='text;FMT=Delimited(;);HDR=YES'";
OleDbConnection conn = new System.Data.OleDb.OleDbConnection(connstring);
System.Data.OleDb.OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
try
{
conn.Open();
da.Fill(dt);
}
catch (Exception ex)
{
Console.WriteLine(filename + "not found");
}
finally
{
conn.Close();
}
return dt;
}
}
My connection string in the Text visualizer when I run in debug mode:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Data\Positions.csv;Extended Properties='text;FMT=Delimited(;);HDR=YES'
I'm getting an exception
base {System.Data.Common.DbException} = {"'Data\Positions.csv' is not a valid path. Make sure that the path name is spelled correctly and that you are connected to the server on which the file resides."}
Can anyone point me in the right direction? I have limited experience doing console apps so it's probably some formatting mistake that I've made. Thanks
and create a folder in the project called 'Data'.
That doesn't work. Your program is running in the bin\Debug subdirectory of your project. It doesn't have a Data subdirectory. You'd have to use ..\..\Data\Positions.csv to find that file.
Well, that would solve your problem right now but it isn't going to be useful once you copy your program to another machine. There won't be a ..\..\Data directory there. Think about ways that your user is going to tell you where the .csv file is located. A GUI with OpenFileDialog is the friendly way but not very compatible with a console app. The standard way for that is to pass command line arguments. Environment.CommandLine. Not very compatible with the typical user. You'll have to weigh these options by yourself.

Categories