I have DataClasses.dbml file in my C# winforms project. This automatically adds a setting of type ConnectionString to Settings file of the project. The connection string throughout the project is accessed using this setting.
Now when I work on my PC, it connects to the database and works fine. But how to set a new connection string depending on client's host and instance names in the settings file permanently and for once (during setup).
I tried doing:
Settings.Default.ConnectionString = "SqlConnectionString";
Settings.Default.Save();
But it gives a compile-time error that its Read-Only.
My only aim is to set the connectionstrings according the clients setting. I dont want to make it hard coded.
Add a partial class definition like the following
public partial class DataClasses
{
partial void OnCreated()
{
Connection.ConnectionString = SQLHelpers.GetConnectionStr();
}
}
where SQLHelpers.GetConnectionStr should lookup the settings from the users App.Config file.
Remember to put this in a separate file to your auto-generated dbml file.
Related
I am developing an MVC5 application and it is a requirements that all environmental configuration be stored outside of the application to enable simple deployment between environments. i.e. When a change is made, copy a bunch of files and don't worry about overwriting the web.config.
I have moved all the configurable settings to a SQL table which works fine, however, I am struggling to move the Connectionstrings outside of the web.config.
I am using EntityFramework within a C# MVC application. I am also using ELMAH for error handling.
I have tried executing the following from the Global.asax, but EntityFramework complains the connection string is not in the file:
private static void SetConnectionString(string connectionStringName, string connectionString)
{
var settings = ConfigurationManager.ConnectionStrings;
var element = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
element.SetValue(settings, false);
collection.SetValue(settings, false);
settings.Add(new ConnectionStringSettings(connectionStringName, connectionString));
collection.SetValue(settings, true);
element.SetValue(settings, true);
}
Is it possible to override the configurationmanager that Entity framework uses?
Edit: Solution.
So the solution was actually pretty simple. As i was using Code First EF I can actually pass in the connection string into the constructor:
public AdventureWorksDb(string connectionString) : base(connectionString) { }
So, with the combination of the two, loading the connectionstrings from XML and modifying the ConnectionStrings Collection at runtime and then passing the correct connection string into the DBContext constructor I have a working solution.
As Ewan mentioned, you can use the machine.config file for this purpose. You can also use the root web.config file. Both of these files are located in the %WinDir%\Microsoft.NET\Framework[64]\[FrameworkVersion]\Config\ directory.
The application web.config file will override any settings in the machine-level files. So, the solution is to exclude your connection strings from the application web.config file that you deploy in order for the application to pick them up from the machine-level file.
I am using Entity Framework. The connection string is currently saved in the app.config file, which by default creates a new file called APPLICATION_NAME.exe.config and copies it to the output folder when building.
Now I don't want my connection string to be visible to the world when I am creating applications, so one way is to create another config file as a resource and reference it in the application.
EDIT:
I am developing using WPF, now is there any special configuration for it doing the below:
How to register an embedded config file in the application ?
Normally when you create your own DbContext, you pass the connection string like this
public MyDBContext() : base("name=Connection_String_Name_In_AppConfig")
so how to tell the DbContext classes to take the connection string from the newly created config file?
Q1. How to register an embedded config file in the Application
You do not. But nothing stops you do "program" code that takes your own configuration information from wherever you want and uses that.
Q2. How to tell DBContext classes to take the DB connection from the newly created config
file ?
You do not. But you can actually pass in an code created connection toe a DbCOntext, in case you did not see that in the documentation.
And seriously, NOTHING in here has ANY relationship to WPF, so that tag you added is just not a good smart move.
To embed a file into the assembly, select the file in the solution explorer and go to Property window then select Build Action as 'Embedded Resource' and Copy to Output Directory as 'Do not copy'. This way the XML config file will get embedded in the assembly.
Now in your Host application(here WPF), you can read the resource file content and then pass the connection string data to your DBContext.
Example to read embedded file from the assembly:
private const string strFileName = “XMLFile.config”;
var assembly = Assembly.GetExecutingAssembly();
var stream = assembly.GetManifestResourceStreamthis.GetType(), strFileName);
var doc = new XmlDocument();
try
{
if (stream == null)
{
throw new FileNotFoundException(“Couldnot find embedded mappings resource file.”, strFileName);
}
doc.Load(stream);
}
catch (Exception ex)
{
throw ex;
}
Hope this will help you
I have a sample application hosted on Github that exactly does what you want.
I developed a class library that uses Linq To Sql to communicate with a database.
When I added this I used Server Explorer to add a database and all the tables I want to talk to.
It then built a .dbml file for me.
In the "Designer" file I can see:
public TPDataContext() :
base(global::TPAPI.Properties.Settings.Default.TruePotentialConnectionString, mappingSource)
{
OnCreated();
}
If I update the "Linq to SQL" it regenerates a new designer.cs file
It stored the connection string in Settings.settings with the scope of "Application".
All functions just fine.
But, I have then added a winfoms project that needs to change this setting. So I added the following code:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.ConnectionStrings.ConnectionStrings["TPAPI.Properties.Settings.TruePotentialConnectionString"].ConnectionString = txtConnectionString.Text;
config.Save(ConfigurationSaveMode.Modified, true);
ConfigurationManager.RefreshSection("connectionStrings");
This updates the connection string in the dll but it only takes effect when the application is shutdown and restarted.
When I am upgrading clients it overwrites what the user had already entered when using it previously.
I cannot seem to work out the best way to:
Not overwrite previous user defined connection string when the app is upgraded.
Be able to save the new connection string and use it without having to stop/start the app.
Having had a read of other threads it appears that the dll shouldn't really have any "local" settings in it (?) and they should all be sent by the winforms app. But, I am unclear on how use Linq to Sql in the dll without it automatically looking/adding it's own connection string.
Can anyone help please?
Thanks
I have decided to rewrite all my DataContext calls to accept the connection string parameter.
I had to amend and test about 40 functions but now the connection string is stored in the winforms application as a user setting and overrides the default connection string generated by Linq to SQL.
So, now in my dll it now looks like
TPDataContext db = new TPDataContext(connStr);
HTH
I have a desktop WPF application which uses Entity Framework 4.1 Code First approach to manage data.
EF adds a connection string to the App.config file and I wan't to be able to change this connection string at runtime.
Scenario is like this:
When I deploy the application it has a default connection string in the App.config file. The user runs the application and since the connection string will probably be invalid for the user (because of server name, user id and password) I will display a server configuration window.
Here user will enter the valid information about his connection and press OK. I will then be able to change the App.config file and save the user's new valid information to the file.
Problems:
If I change it using ConfigurationManager, the changes will be temporary meaning that the file is not saved, changes are made in memory.
If I read the App.config file into a stream, make required changes in the memory, delete physical file and save the in memory stream as App.config again, Windows will not let me make changes to files under ProgramFiles folder.
What is would be the best approach here?
EDIT: Problem Again!
After I modify the App.config file with this method:
private void ApplyChangesToConnectionString()
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var connectionStringsSection = (ConnectionStringsSection)config.GetSection("connectionStrings");
connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString = GetChangesAppliedConnectionString(connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString);
config.Save(); // This line throws an exception
ConfigurationManager.RefreshSection("connectionStrings");
}
config.Save(); method call throws an error saying
"Access to "C:\Program Files (x86)\MyCompany\MyApp\MyApp.exe.config"
is denied."
I know that files under "Program files" are immutable, so how can I handle this?
I couldn't modify ConfigurationManager.ConnectionStrings["key"] object, because it is readonly.
So I decided to add a new connection string to my App.config file so it looks like this:
<connectionStrings>
<add name="SomeUniqueName" connectionString="Data Source=(local)\SQLExpress;Initial Catalog=MyDb;User Id=sa;Password=password; MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
and then changed my DbContext constructor to take newly added connection string like this:
public MyContext()
: base("name=SomeUniqueName")
{
}
Here, the value of name attribute at connection string and constructor must match.
Then to change this newly added connection string at runtime I used a method like this:
private void ApplyChangesToConnectionString()
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var connectionStringsSection = (ConnectionStringsSection)config.GetSection("connectionStrings");
connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString = GetChangesAppliedConnectionString(connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString);
config.Save();
ConfigurationManager.RefreshSection("connectionStrings");
}
App.config is not the proper place to do this since it's a global configuration used by the application.
I recommend you to save the settings per user. See this related question : c# - approach for saving user settings in a WPF application?
App.config is the correct approach in my opinion, however I wouldn't rely on writing the file physically yourself. Instead, allow the framework to do the heavy lifting for you.
Check out the sample here.
EDIT: Glad Sandeep's comment above has helped you. Feel free to check out that link too if you want a bit more information!
I am currently developing a ASP C# web application. I have created a settings page which is going to hold MySQL Database Connection Settings.
I have an ASP page with a form that allows the user to modify the MySQL Database connection settings. When the user submits the form it gets the value from the text boxes and is supposed to modify the settings will with the new connection settings. However, VS2010 is reporting an error that says property or indexer cannot be assigned to -- it is read only.
How can I go about modify these settings.
Thanks for your help.
Chris Board
Edit: Change variable names
System.Configuration.Configuration updateWebConfig =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("\\");
System.Configuration.ConnectionStringSettings conStringSettings = updateWebConfig.ConnectionStrings.ConnectionStrings["testConString"]; //your connection string name here as specified in the web.Config file
conStringSettings.ConnectionString = txtCon.Text; //Your Textbox value here
conStringSettings.CurrentConfiguration.Save();
This will open the root web.config file in your website and update the connection string there. For more information on updating the web.config in runtime look here Under "Updating Configuration Settings"