Relative path to DB in connection string - c#

I am developing a db application in C# and my current connection string is
#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Shop.accdb;Persist Security Info=False;"
How can I modify it so that the db is in the folder of the project and not in D? I mean I am planning to send the project to a friend so I don't want to include the full path but just the folder of the project.
Thank you in advance!

Change your connection string to
#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Shop.accdb;" +
"Persist Security Info=False;";
|DataDirectory| is a substitution string that (for WinForms apps) will be set by the Framework to the value of the current directory.
In code (before any Data Access) it could be changed to something to your likes with
AppDomain.CurrentDomain.SetData("DataDirectory", #"D:\temp");
See this thread on MSDN
However, keep in mind, that, if your reason to change that value arises for permissions problems, you would have the same problems storing your database in the same folder with your program (C:\program files) because that folder is also severely write restricted. The best way is to store your database in a subfolder of C:\PROGRAMDATA\<myAppDatabaseFolder>
string myFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
myFolder = Path.Combine(myFolder, "myAppDatabaseFolder);
AppDomain.CurrentDomain.SetData("DataDirectory", myFolder);
(I suppose that your setup procedure creates the MyAppDatabaseFolder so I have no check for folder existance)

Related

C# building/resource/publish/create and exe file with database

I was wondering how can I create the exe file for the app I made. I tried giving the exe file in the bind/debug folder together with the database (MS Access). But having an error with the filename of the mdb file, it is pointing to my directory.
{
InitializeComponent();
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;
Data Data Source=C:\Users\asdf\Documents\questionbank.mdb;
Persist Security Info=True;
Jet OLEDB:Database Password=asdfasdf";
}
And the error getting is "Windows cannot access the specified device, path, or file. You may not have the appropriate permission to access the item.
Put your connection string in a configuration file, eg., by createing a setting in the Settings tab when you right click on your project and go to Properties.
Hard coding your connection details, as you've done, means it cannot change when you deploy your application.

C# Connection string save into AppData?

So I have a DB (webster.accdb) which will be getting installed on a server (eg. \SERVER\WEBSTER)
However different locations may have differing SERVER names (ADMIN1 etc etc)
When the program originally installs, it checks the con string in app.config which I have put as "DEFAULT" - literally the string.
The program checks the connection string in app config, and if it is DEFAULT, then it runs a little prompt i have made which asks for details from the user regarding the server name and a few other specifics.
They click "connect" and it writes the newly constructed connection string to app.config and the program loads after a series of tests.
Now this works under VS tests and installs on D: drives in temp folders. My issue is that if 'properly' installed to the programfiles section, then we now have the issue of access being denied to alter the file.
So could someone point me in the right direction with regards to the correct process as i know I'm doing it wrong:
Create an XML in Appdata for the user, which has the con strings, and this is generated on first use, and is used for the constrings from then on?
Save the con strings as Settings, and use This code to update settings, then make sure all my con strings in my program no longer point to configuration, but to settings??
Something better because I am clueless and this is totally not how i should be doing this at all!
Code used to update the config:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.ConnectionStrings.ConnectionStrings["LOTSConnectionString"].ConnectionString = "Data Source=" + txtpcname.Text + ";Initial Catalog=" + cmbdispense.SelectedItem + ";Integrated Security=False;User ID=webbit;Password=ill923r6MG";
config.Save(ConfigurationSaveMode.Modified, true);
Access Denied means the user which is executing the app either does not have permission or because of inbuilt security by Operating System, app is executing under restricted permissions. Try executing app with Administrator by right clicking on it and choosing run as.
You can prevent this by Setting up connection string at the time of installation instead. Prompt a user to enter details during installation.
So pretty much I self confess to not understanding the benefits of the USER section of the config.
I have changed my connection strings to just "STRING" and put in the USER section of Settings.
Now i can refer to my strings as
properties.settings.default["ConString"].tostring
This is then saved to User/APPDATA/Local
For noobs like me reading this, that means the original app.config file in programfiles stays THE SAME, but an excerpt is taken out of it relating to the user section and put into appdata.
What was confusing me the whole time was selecting "connection string" in settings, which didnt allow selection as a USER setting.

Connectivity between access database and c#

I was checking about access database connectivity with c# in social of MSDN where i found the sample connection string as follows
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\abc.mdb;Jet OLEDB:Database Password=password";
Now my question is suppose i have created a form application and i put the database file abc.mdb at the same location where the .exe file resides. In that case can i write the connection string as follows?
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=abc.mdb;Jet OLEDB:Database Password=password";
I was trying this with SQL database file but it was not running may be the full path is mandatory for this case. I'm i right?
If you can't use a relative path in connection string, you can generate it at runtime something like:
string connstring = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Persist Security Info=true", Path.Combine(Directory.GetCurrentDirectory(), "MyDatabase01.accdb"));
try, (although not tested)
string dbpath = AppDomain.CurrentDomain.BaseDirectory + "abc.mdb";
string ConnStr = String.Format(Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Jet OLEDB:Database Password=password;", dbpath)
To answer your first question, yes, having the .mdb file in the same directory will work with your second connection string.
Assuming you meant a MSSQL or MSSQL Express in the second "question," you need to specify the SQL Server instance as part of the connection string.
For ASP.NET 2.0 or higher, the database file (.mdb or .accdb) should always go into the App_Data folder. There are two reasons for this: first, App_Data is configured to prevent users from browsing to the folder and downloading a copy of your database. Second, you can take advantage of the special DataDirectory token (or substitution string) to reference the file within a connection string. DataDirectory defaults to the App_Data directory.
So your Access datasource goes like this.
<asp:AccessDataSource
ID="AccessDataSource1"
runat="server"
DataFile="~/App_Data/MyDb.mdb"
SelectCommand="Select * From MyTable">
</asp:AccessDataSource>
I have not tested this, but the DataDirectory substitution string could be used.
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\abc.mdb;Jet OLEDB:Database Password=password";
Then you could do
AppDomain.CurrentDomain.SetData("DataDirectory", #"D:\MyApp");
As describe in the following KB article:
|DataDirectory| substitution string support
|DataDirectory| (enclosed in pipe symbols) is a substitution string
that indicates the database path. Therefore, you do not have to
include the full path in the code. When you include the full path in
the code, you may experience problems because the full database path
can be serialized in different locations. The |DataDirectory|
substitution string also makes it easy to share a project and to
deploy an application.
For example, if you include the full path in the code, the application
can have the following connection string.
Data Source= c:\program files\MyApp\Mydb.sdf
If you use the |DataDirectory| substitution
string, the application can have the following connection string.
Data
Source = |DataDirectory|\Mydb.sdf
To set the DataDirectory property, call the AppDomain.SetData method. If you do not set the DataDirectory
property, the following default rules are applied to access the
database folder:
For applications that are put in a folder on the
user's computer, the database folder uses the application folder.
For
applications that are running under ClickOnce, the database folder
uses the specific data folder that is created.

Error opening connection to SQL CE file on test machine

I'm testing my application on a non-administrator windows 7 account. The application is installed into program files. This includes the .sdf file I need to read from. I've got the connection string marked as read only and set the temp path to my documents. This is the error that it spits out when I try to do connection.Open()
Internal error: Cannot open the shared
memory region
I've got the connection string defined in app.config, but I'm modifying it before I start using the connection. This part is in app.config Data Source=|DataDirectory|\DB.sdf;Password=password;
And then I modify it like so:
connection = new SqlCeConnection(connectionString +
";Mode=Read Only; Temp Path=" + Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
This works on my developer machine (obviously) since its running from outside of a read-only directory. But even when I manually mark the .sdf file as read-only it still works, and successfully creates the temporary db file in the correct folder. However, on the test machine everything is located in a read-only program files folder, and it doesn't work.
The main goal of this problem is trying to make sure my program doesn't have to be ran as an administrator, and I would like to keep from moving the main copy of the db file from outside of the installation directory.
Let me know if I need to explain anything else. Thanks
I'm using a sql ce database too and had the same problems. my solution was to create the database in a subfolder in Environment.SpecialFolder.CommonApplicationData. If only one user will use it you can create it in Environment.SpecialFolder.ApplicationData. But here you don't need admin rights.
Another point is your connection string in your app.config. If you'll modify it in your program like me, it must be located in such a 'non-admin-right-needed' folder too. I have a static app.config in my app-folder in program files, but a second one with the connection string in Environment.SpecialFolder.LocalApplicationData (this is 'username\AppData\Local' in Win7). And I protect my connectionstring with DataProtectionConfigurationProvider encryption, so no one can read the data base password.
This is how you can map your second app.config to your app:
string ConfigPathString = #"{0}\MyApp\MyApp.config";
string ConfigPath = String.Format( ConfigPathString, System.Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData ) );
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = ConfigPath;
Configuration Config = ConfigurationManager.OpenMappedExeConfiguration( fileMap, ConfigurationUserLevel.None );
string myConnectionString = ConnectionStrings.ConnectionStrings["MyConnectionStringKey"].ConnectionString;
Like Calgary already mentioned in his comments you can't really open the file directly in the programs folder due to the restrictions of Windows 7 to non-admins. But due to the fact that you don't want to write anything into it, why don't you simply copy at startup the file into Environment.SpecialFolder.ApplicationData?
When your program starts up simply copy the file out of the programs folder into a proper location, use it as you like and delete it on application exit. So you don't leave any fragments (except the application would crash).
Just to be sure for the last scenario, you could add an additional delete operation to the setup deinstallation routine. So if the application will be removed and it crashed at the last start the setup will remove the trash, leaving the machine as before the installation of the software.

Help with connection string

So I'm trying to connect to my database at the specified location, and the connection is established as long as the db at the same location specified at DataSource field, but what if I tried to distribute my application, the file path will change and will lead to errors I want to avoid. Here is my connstring:
string connstring = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC1\Documents\Visual Studio 2008\Projects\Test\Test\bin\Debug\MyDatabase01.accdb;Persist Security Info=true";
Is there anyway I can define DataSource location to be at the same folder?.
There are a few things I can think of to do:
Store the database next to the application and then use a relative file path in the connection string (this makes use of a substitution string built into ADO.Net - see here for more info):
string connstring = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\MyDatabase01.accdb;Persist Security Info=true";
Store your connection string in a configuration file. This can then be changed when your application is run on a machine where the database is in a different place.
Have your application prompt for the location of the database on first use and then save that location to as settings file to use in the connection string.
If you are distributing your database with the application, option 1 is the best. If not, I would go for option 3.
If you can't use a relative path in connection string, you can generate it at runtime
something like:
string connstring = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Persist Security Info=true", Path.Combine(Directory.GetCurrentDirectory(), "MyDatabase01.accdb"));

Categories