Using web.config connection string in data access project - c#

I'm on .NET 4.6.1, Visual Studio 2015, SQL Server Developer 2016. I want to specify my EF connection string in my main project's web.config, but I cannot for the life of me figure out how to reference that in my data access project. Every answer I can find says to do the same as in this one--that is, use this:
System.Configuration.ConfigurationManager
.ConnectionStrings["connectionStringName"].ConnectionString;
When I use that, however, the valid connection string isn't being passed. It's instead getting one that appears to be the default; the data source is being set to .\SQLEXPRESS when I have no string with that defined anywhere. Searching all files in the solution for SQLEXPRESS returns no results, so it's not hardcoded anywhere.
What is the correct way to pass my connection string from my main web.config (with the relevant transforms per build) to my data access project?

There is only one app.config / web.config that will be read from at run time and that is the config associated with the applications entry point. So if you have a web project and a referenced project that serves at the data access layer and you want to read a connection string from the config the web.config of the web project is used. The same is true for a windows application or wpf etc, only the applications main entry point's configuration will be used. Once your application is running you can reference that app.config / web.config from anywhere in your code though as you generally do this using string identifiers.
In other words if you have a project with your Data Access compiled to MyDA.dll and you app.config in that project that might be output to MyDA.dll.config (this does not happen by default) anything you have in MyDA.dll.config is ignored at runtime. The file will not be read from, only the web.config will be used OR the app.config of the .exe's entry point.
For Entity Framework's DbContext you can pass the name of the connection string directly to the constructor. You do not have to retrieve the connection string and pass it yourself. So give each connection a specific unique name in your web.config.
<connectionStrings>
<add name="ConnectionName1" connectionString="Data Source=(local);Database=YourDB;User Id=YourUser;Password=yourPassword" providerName="System.Data.SqlClient" />
<add name="ConnectionName2" connectionString="Data Source=(local);Database=YourDB2;User Id=YourUser2;Password=yourPassword2" providerName="System.Data.SqlClient" />
<!-- more here -->
</connectionStrings>
Then in your code you can create your Entity Framework's DbContext using that name.
var myEntities = new MyEntities("ConnectionName1"); // MyEntities is some class that derives from DbContext
In my past projects the DbContext I work with usually always maps to one database at run time. What I mean here is I would not use the same DbContext type multiple times pointing to different databases. In this case I hard code that name right into my DbContext type and make sure that my consuming applications have that connection name listed in the web.config or app.config respectively.
public class MyEntities : DbContext {
public MyEntities() : base("ConnectionName1") {}
}
// calling code now never has to know about the connection
using(var myEntities = new MyEntities()) { /* do something here */}
Alternatively if you really do want the complete connection element you can reference System.Configuration (add it to your project references in the project where you make the following call) and call it this way.
var connection = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionName1"];
var conString = connection.ConnectionString; // you can also get the provider
var myEntities = new MyEntities(conString);
I have not used this approach in a while but maybe there is a good reason to use it in your case.

The data source is being set to .\SQLEXPRESS when I have no string with that defined anywhere. Searching all files in the solution for SQLEXPRESS returns no results, so it's not hardcoded anywhere.
Its hardcoded in your machine config file. Simply add:
<clear />
Above your first connection string to remove it.
You could remove the .\SQLExpress connection string from line 126 in the machine.config, however IMHO play on the safe side and dont mess with machine config, preferring to use <clear /> instead.

Have you tried connection to the Server Explorer -> Data Connections and having the property auto generated? Next thing I would tried is adding an ADO.Net data model and pointing to the correct DB with the Access driver. It may be as simple as provider on the configuration string.

Here is a simplified example and/or proper way given by MSDN:
var connectionString = ConfigurationManager.ConnectionStrings["connectionStringName"].ConnectionString;
config file like the following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name="connectionStringName" connectionString="Data Source=(LocalDB)\v11.0;Initial Catalog=DatabaseName;Integrated Security=True;Pooling=False" />
</connectionStrings>
</configuration>
Needed namespaces:
System.Configuration
From : https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.connectionstrings(v=vs.110).aspx

As far as I remember, when using EF, it creates a connection string that matches the name of the context you defined, so, if your context is named MyContext then you should define a connection string with that name in your app/web.config. To save you the trouble of writing the EF connection string on your own (which is much longer than a regular ADO.Net connection string), just copy the one that was generate in the DLLs .config file.
Once you have that, you can use the configuration transformation functionality built into web projects, that allows you to change portions of the .config file depending on the current build configuration, for example:
web.config - Will hold the DEVELOPMENT connection string.
web.staging.config - will hold a replace transformation with the STAGING connection string.
web.release.config - will hold a replace transformation with the RELEASE connection string.
Hope it helps!

<configuration>
<connectionStrings>
<add name="CONNECTIONSTRINGNAME" connectionString="server=.; Database=YOURDATABASENAME;Integrated Security=true;" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
change the capital letters with your own data

Related

C# Configuration Manager when executing Unit Test is referencing machine.config rather than app.config

I have read many other post about fixing the issue for NullReferenceException when calling ConfigurationManager.ConnectionStrings as well as what to do when Unit Test is using machine.config rather than app.config but none have worked for me. Below is a list of approaches that I've tried and have been unsuccessful with so far.
Add Existing Item to unit test and reference the app.config for the project you are testing against
Copy the app.config from the targeted project and paste it in the unit test project
Ensure the bin folder of the unit test project is copying the appropriate config file
Set the properties for the unit test to copy to output as always
Below is a copy of my current config within the Unit Test project:
<configuration>
<appSettings>
<add key="Environment" value="Development" />
</appSettings>
<connectionStrings>
<add name="Connection.Development" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDB)\***;Initial Catalog=***;Persist Security Info=True;Integrated Security=True;Pooling=False" />
</connectionStrings>
</configuration>
I am expecting the following line of code to return Connection.Development connection string but instead I get the LocalSqlServer connection string from the machine.config consistently
string connectionString = ConfigurationManager.ConnectionStrings["Connection.Development"].ConnectionString;
I am using VS2017, running .Net Core 2.0, and trying to connect to local MS SQL Db within the application. If someone could tell me how they fixed this problem for their issue it would be greatly appreciated. If you know why, please pass that information along as well.

Dynamic use of multiple config files in C# application

I've done a lot of research on this, and tried a number of approaches, but I'm beginning to think that what I want to do can't be done. To wit -- I am building an application that will be used by multiple clients. Each client will have their own database connection requirements, and their own set of customizations to control some of the behaviour of the application.
What I want to do is to create a .config file for each individual client, then use a command-line argument that will specify which .config file to load. Each config file will have its own section, and its own . I've gone through much of the documentation con ConfigurationManager and the Configuration classes and tried a number of different approaches, all of which have failed.
The basic question is "when I open a .config file, how do I tell the application to make this .config the default configuration?" For example, when I later make reference to a value in appSettings, or a database connection string, how do make sure that these references will each map to the custom configuration I have loaded, and not the one created by default by Visual Studio?
I have found all kinds of references to loading configuration files, but nothing that tells me how to dynamically replace the standard one with the one I just loaded. I keep ending up with null reference exceptions and running headlong into brick walls.
You can have multiple connection strings defined in your config file, then refer to them by name.
Example:
<configuration>
<connectionStrings>
<add name="client1Connection"
connectionString="Data Source=(local);Initial Catalog=dbclient1;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="client2connection"
connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=dbclient2;Integrated Security=True"
providerName="System.Data.SqlClient" />
...
</connectionStrings>
</configuration>
You can refer to them in you c# code by:
string client1ConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["client1Connection"].ConnectionString;
string client2ConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["client2connection"].ConnectionString;

SqlConnection Data Source , need to be changed when working on different PC

I am using the following code
SqlConnection con = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=C:\\Users\\mr\\Desktop\\ment Final\\ment Final\\App_Data\\LoginStuff.mdf;Integrated Security=True;User Instance=True");
So every time I run the project on new PC I have to change all the Data sources again and again . is there any to avoid that ?
Instead use connection strings and the web.config for easing changes.
web.config example:
<configuration>
<connectionStrings>
<add name="LoginDB" connectionString="Data Source=.\\SQLEXPRESS;AttachDbFilename=C:\\Users\\mr\\Desktop\\ment Final\\ment Final\\App_Data\\LoginStuff.mdf;Integrated Security=True;User Instance=True" />
</connectionStrings>
</configuration>
Change your code to:
SqlConnection con = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["LoginDB"].ConnectionString);
You likely already have a web.config in the root of your project and you can simply add this connectionStrings section or just add this new connection string if the section already exists!
Use config file. Can be found in root of the project as web.config in ASP.NET and app.config in class and windows project
<connectionString>
<add
name="connStr"
connectionstring="Server=myServerAddress;
Database=myDataBase;
Trusted_Connection=True;"
</connectionString>
In cs
SqlConnection conn = new SqlConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
To reiterate what Amit and Subterfuge said above, your connection string should be stored in a configuration file instead of in the code. Those methods won't solve the face that you would still need to modify the connection string on every machine though. Instead, I recommend you create a convention for local development and use configuration transforms between development/staging/production environments.
Local Development Convention
It will be easiest to develop against your code locally if you put the database in the same location on every machine. The .NET convention is to use the app_data folder in your project's root folder. If you place your database in this folder on each machine you're developing on then you won't need to change the connection string.
For example, copy LoginStuff.mdf into your project's /app_data folder (create the folder if it doesn't exist). Change your connection string to:
<connectionString>
<add name="loginStuff" connectionstring="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|LoginStuff.mdf;User Instance=true"
</connectionString>
Then in code you can reference it by adding a using to System.Configuration and then referencing the connection string:
var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["loginStuff"].ConnectionString);
Between Environments
Between environments (debug, release, etc) you can use configuration transforms to modify the web.config automatically. For each environment you need to create a web.{environment}.config file in your project's root directory. Use XML transformations to specify how you want to modify your configuration file.
These should cover your two most common scenarios. Cheers!

Unable to retrieve metadata - MVC application

I was following this to create a simple MVC application. After creating the model, when I tried to add controller, I got the following error :
Unable to retrieve metadata for "MvcApplication.Models.Movie". Invalid value for key "attachdbfilename".
Can someone tell why I am getting this error.
Update : I saw this wherein solution is provided by changing the providerName. But in my case it is already System.Data.SqlClient. Following are my connectionStrings :
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=aspnet-MvcApplication-20130708120940;Integrated Security=SSPI" providerName="System.Data.SqlClient" />
<add name="MovieDBContext" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
The error message is saying invalid value for AttachDbFilename which is part of your MovieDbContext connection string.
The connection string currently shows this AttachDbFilename=|DataDirectory|\Movies.mdf so it appears the mdf file is now missing from the App_Data folder.
I found the solution. the problem is the "|DataDirectory|". I Changed "|" to "\"
I just solved this problem. Even though I am new to MVC, I am bit embarrassed to say, I was trying a work around for another problem I was having and moved my SetInitializer into my classname : DbContext class.
The app worked just fine and the database was created fine as I changed the models but I couldn't add new controllers or modify current controllers using the scaffolding tool.
I began receiving errors. One of them is listed above and another is:
Unable to retrieve meta data for 'namespace.Models.class'. A file
activation error occurred. The physical file name '\name.mdf'
may be incorrect. Diagnose and correct additional errors, and retry the
operation.
CREATE DATABASE failed. Some file names listed could not be created.
Check related errors.
Moving the SetInitializer back into my Global.asax fixed the problem.

How do I ensure that the right app.config is being loaded?

I have a console app, let's call it Test.Console. This app uses a project called Test.Code.
Test.Code is a wrapper to access a database and should have an app.config file containing the connection string.
Test.Console should then access the classes in Test.Code to access what's in the database.
However, when I put the connection string in the app.config in the Code project, it doesn't seem to be able to access it, but when I put it in app.config in the Console project, the code in the Code project seems to be able to access it.
Is there any way that I can put the connection string in the Code project rather than the Console project?
Edit:
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<clear />
<add name="ACE" connectionString="data source=servername;database=ACE;userid=username;password=password"/>
</connectionStrings>
</configuration>
In my class:
string connection = ConfigurationManager.ConnectionStrings["ACE"].ConnectionString;
That's it at the moment.
The app.config is exactly that, configuration for the running application.
The running application should be in charge of what databases etc that it connects to, hence the reason the config goes there.

Categories