How to Register Windows Forms with Simple Injector

How do I read the current path of |DataDirectory| from config settings

|DataDirectory| does not come from config settings; you're mixing up three different things:

ConfigurationManager.AppSettings["DataDirectory"]

This comes from config settings; a .config file you have to create and put into your project. This particular setting is the value of the element with key "DataDirectory" in the AppSettings element. This doesn't exist unless you put one in the .config file. Typically this is where you put configuration or startup data that is never changed. You should not put file paths here, as they can be different on the machine users install your database to.

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

This is the path to the current user's roaming application data folder defined by the operating system your app was installed on. You cannot change this, it is defined by the OS. You can be sure this folder is writable by the user, will not be deleted if the user uninstalls your application, and will be available if the user roams or logs on from another machine. This is typically where you want to put editable application data.

SqlConnection("Data Source=|DataDirectory|DatabaseFileName.sdf;...")

This is a connection string for an ADO.NET connection. ADO.NET treats vertical bars specially, it looks for an AppDomain data matching the key name between the vertical bars. You can get the same data with:

AppDomain.CurrentDomain.GetData("DataDirectory")

So what writes the value of DataDirectory? It's done by whatever deploys your executable:

  • .MSI installers define it as the app's target folder.
  • ClickOnce defines a special data folder in your project.
  • Web apps use the App_Data folder.
  • The Visual Studio debugger uses the debug folder.

Note that .MSI installers can allow the user to change the DataDirectory; this is why you should never hard-code or change DataDirectory, if you do that there is no way to find where your application data was deployed. You typically use the DataDirectory folder for read-only binary data deployed with your executable.

If you need to write to the data deployed with your executable you should first copy it someplace you know the user will be able to write to, such as to Environment.SpecialFolder.ApplicationData, and write to the copy. Not only is DataDirectory not necessarily writable by users, it is part of the deployment and not part of the user data; if you repair or uninstall your executable then DataDirectory gets reinstalled or deleted. Users don't like it when you delete their data, so don't save it to DataDirectory.

|DataDirectory| in Project properties Settings

This has been asked before. This MSDN post gives a good overview.

It should indeed default to your binaries folder, you can change it with AppDomain.SetData() . If you change it, better do it early.

C# local database not updating when using |DataDirectory|

|DataDirectory| variable has a value set by the .NET Framework based on the OS.

I did a quick experiment with this as following.

class Program
{
static void Main(string[] args)
{
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory");

Console.WriteLine(dataDirectory);

Console.ReadKey();
}
}

When I ran above code, it displayed nothing. Upon debugging I figured that the dataDirectory variable has value null.

Then I tried to use it to create database connection and open it.

 SqlConnection conn = new SqlConnection(@"Data Source=.;AttachDbFilename=|DataDirectory|\HomeDB.mdf;Integrated Security=True");

conn.Open();

This code failed at conn.Open(); with following error.

An attempt to attach an auto-named database for file D:\Chetan\Sandbox\consoleapp1\ConsoleApp1\bin\Debug\HomeDB.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.

As you can see from the error that, because '|DataDirectory| is null, the application tries to locate the .mdf file at bin\Debug folder under the project directory which is basically the location from where the exe is running.

So if you want the |DataDirectory| have different value, you first need to change it before using it. As following.

class Program
{
static void Main(string[] args)
{
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory");

//Changing DataDirectory value.
AppDomain.CurrentDomain.SetData("DataDirectory", "C:\\DataFiles");

Console.WriteLine(dataDirectory);

SqlConnection conn = new SqlConnection(@"Data Source=.;AttachDbFilename=|DataDirectory|\HomeDB.mdf;Integrated Security=True");

conn.Open();

Console.ReadKey();
}
}

With this code, I noticed that the value "C:\\DataFiles" was used to locate HomeDB.mdf.

If you read This it explains the order in which values of |DataDirectory| are expanded.

This explains about how to customize the value of |DataDirectory|.

Now coming to your issue of data not being reflected.

In your case, |DataDirectory| has null value, so it is connecting to the HomeDB.mdf file located at the bin\Debug or bin\Release folder making changes there while you are looking at F:\Project\Home_Database\HomeDB.mdf to verify the changes.

You are not seeing the error which I am seeing because the .mdf file is copied to the executable location when you are building the project.

So solution to your problem is to change the value of |DataDirectory| using AppDomain.CurrentDomain.SetData("DataDirectory",<<yourvalue>>); method.

EDIT:

If the location of .mdf file is fix relative to the executable file of the project, you can build the value for |DataDirectory| at runtime and assign it.

Let say, you have a folder Database at the same location as the exe and Database folder has HomeDB.mdf file. So first you need to find the path from where the exe is running and append Database to is and assign it to |DataDirectory|.

//Get the current path from where the exe is running.
var currentDirectory = AppDomain.CurrentDomain.BaseDirectory;

//Build path to Database folder
var databasePath = currentDirectory + "Database";

//Assign it to DataDirectory
AppDomain.CurrentDomain.SetData("DataDirectory", databasePath);

var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory");

Console.WriteLine(dataDirectory);

//Use DataDirectory to SQL Connection.
SqlConnection conn = new SqlConnection(@"Data Source=.;AttachDbFilename=|DataDirectory|\HomeDB.mdf;Integrated Security=True");

conn.Open();

This would work without any issue no matter from where you are running the application. It will work as long as you have Database folder and HomeDB.mdf file in that folder.

EDIT END

You also might want to consider putting the connection string in the configuration file, instead of hard-coding it into the code itself.

I hope I was able to explain the point clearly and this would help you to resolve your issue.

How to set the current working directory?

Try os.chdir

import os
os.chdir(path)

        Change the current working directory to path. Availability: Unix, Windows.

How to load different .vimrc file for different working directory?

If each project uses a distinct language, the built-in filetype plugin (ftplugin) mechanism, as described by Jamie Schembri, will work just fine. If you really need different settings for the same type of files, read on:

Central configuration

If it's okay to configure the local exceptions centrally, you can put such autocmds into your ~/.vimrc:

:autocmd BufRead,BufNewFile /path/to/dir/* setlocal ts=4 sw=4

On the other hand, if you want the specific configuration stored with the project (and don't want to embed this in all files via modelines), you have the following two options:

Local config with built-in functionality

If you always start Vim from the project root directory, the built-in

:set exrc

enables the reading of a .vimrc file from the current directory. You can place the :set ts=4 sw=4 commands in there.

Local config through plugin

Otherwise, you need the help of a plugin; there are several on vim.org; I can recommend the localrc plugin, which even allows local filetype-specific configuration.

Note that reading configuration from the file system has security implications; you may want to :set secure.

Where to read a data folder and configuration file in .DMG Mac OS file?

I would say there is nothing wrong with having the data folder live side by side with the executable python script in macOS.

I'm assuming this is a script only with no GUI. If there was a GUI, I say the user should be encouraged to copy the application into /Applications (or ~/Applications), then provide a way for the user to select a "data" folder using a dialog box.

I think the best solution, though, that will work for both Windows and macOS is to allow the data directory's path to be specified as a command-line argument. If none is specified, it can default to ./data

If you want to save the user-specified setting for the path to the data directory, a good, mac-like technique is to use the defaults system. You can easily read and write defaults in a script using the defaults read and defaults write commands. Defaults work using reverse domain name notation to help ensure that they are unique across all applications.

Lets say your organization is named ttwidgets, if you had a website named ttwidgets.com and this script is named pywidget, you would use the domain com.ttwidgets.pywidget.

The syntax to set the default is:

% defaults write com.ttwidgets.pywidget datapath /user/specified/path

This is then managed by macOS and stored persistently. You can read back the setting if it exists again later using:

% defaults read com.ttwidgets.pywidget datapath
/user/specified/path

if nothing is set (e.g., first use), you will get an error (and the command returns a non-zero return code:

% defaults read com.ttwidgets.pywidget an_unset_variable
2018-04-21 12:08:40.179 defaults[12409:1472790]
The domain/default pair of (com.ttwidgets.pywidget, an_unset_variable) does not exist
% echo $?
1

This should provide all the tools necessary to use macOS's built-in preferred method for persistently storing key/value settings for applications.



Related Topics



Leave a reply



Submit