Change connString dynamically - c#

I am currently working on an ASP.NET MVC project with Entity Framework. The solution includes the ASP.NET MVC application and a DataProvider project. The project only includes an EF model, as I have a partner who shares a database with me.
The problem is in that, that we don't actually share the same database. What I mean is that the actual server of the database is not the same. We have the same tables. But the connection string has to be changed every single time we pull from our git repository. The string changes in the web.config file of the ASP.NET MVC project and in the app.config file of the EF library.
My question is - if there is a way for our system to detect which PC it is running on and modify the connection string dynamically? Now I do it manually.
<!--PC NICO CEI-->
<!--
<connectionStrings>
<add name="dbShubertEntities"
connectionString="metadata=res://*/ModelDbShubert.csdl|res://*/ModelDbShubert.ssdl|res://*/ModelDbShubert.msl;provider=System.Data.SqlClient;provider connection string="data source=E04\SQLEXPRESS;initial catalog=dbShubert;user id=gereisma17;password=12321;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
-->
<!--PC NICO Laptop-->
<!--
<connectionStrings>
<add name="dbShubertEntities"
connectionString="metadata=res://*/ModelDbShubert.csdl|res://*/ModelDbShubert.ssdl|res://*/ModelDbShubert.msl;provider=System.Data.SqlClient;provider connection string="data source=DESKTOP-I62BLOC;initial catalog=dbShubert;user id=user;password=1234;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
-->
This is what I do now. I am commenting the connection string. I want to automate the whole thing.

You could overload the DbContext's constructor with the dynamic connection string
public class MasterDal : DbContext
{
public MasterDal(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
// DbSet & OnModelCreating etc
}
& then invoke dal in Controller as required
if (logicToGetPc.equal("CEI"))
{
MasterDal dal = new MasterDal("dbShubertEntitiesCEI");
// do mumbai related whatever
}
else if (logicToGetPc.equal("Laptop"))
{
MasterDal dal = new MasterDal("dbShubertEntitiesCEILaptop");
}

if you are using aspnet core there is a way to configure environment variable as override for the app settings
this way you'll have a "default" appsettings.json that contains all the common settings, then on the different machine you can configure environmnet variables that replaces (override) the connection string in different way for each machine
i suppose a similar approach is possible for aspnet for the full framework as well
as your connection string have already a quite specific name "dbShubertEntities" it sould be quite effective to override and you should not risk to have connection string collisions in case you work on different projects.
as reference see https://joonasw.net/view/asp-net-core-1-configuration-deep-dive the part where it uses .AddEnvironmentVariables()

Store the connection string as an environment variable on each PC.
When creating the connection to the database, retrieve the connection string using Environment.GetEnvironmentVariable method instead.

(at time of writing, there's no code)
This is what appsettings.json, (or it's counterparts), was made for.
As i perceive your predicament, (you need more whitespace in your writing to make it easier to read), you are basically working in two different environments, (similar to dev versus test). A simple configuration change would be the simplest way.
As an aside:
Reading between the lines, it seems like you are hard-coding connection strings, and I have a two-word advice for you: STOP IT! (I used to do that, and It's a bad habit that can be hard to shake off)

Related

Correct way to keep writable database for an application

I am creating a writable application database in \AppData\Roaming\ProjectName to keep authorization and cache.
So firstly, i have database.db in my project that i will copy to
AppData, when App is started for the first time. But i have no
idea how write a Connection string in App.Config that case. Now it is:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\cache.db" providerName="System.Data.SQLite" />
</connectionStrings>
Secondly, i am not sure, that i should use App.Config connection , but i`m going to change data a lot of times.
Thirdly, did i chose a right path to keep writable database
or there are any of other ways?
This is how I would reference a sqlite database in the appdata folder. I would not use the ConnectionStrings section of app.config. I would use the connection string builder and use Environment to get the path to the user's app data folder.
SqliteConnectionStringBuilder bldr = new SqliteConnectionStringBuilder();
bldr.DataSource = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"your-program-folder-name",
"your-database-name.db");
var sqliteConnection = new SqliteConnection(bldr.ConnectionString);
in #2 of your question I do not understand what you are referring to about changing data. Do you mean in the database or in the config file?
Regarding #3, you mention this database is used for authorization. If you put the database on the client machine you cannot lock it down. A user can figure out how to circumvent your security. So, if security is any kind of concern you need to put the back end on a restricted server and use a system that employs Role Based Access Control (or similar), and that is a large topic in itself.

Entity Framework creates a database with a wrong name

I have two projects in my solution:
An ASP.NET Web API project with EF
A console app with EF
Both projects are configured to connect to SQL Server and have the same connection string defined in the app/web.config:
<add name="AppContext"
providerName="System.Data.SqlClient"
connectionString="Data Source=localhost\SQLEXPRESS;Database=XYZAC;Integrated Security=True" />
The problem only occurs with the console app. The web app creates the XYZAC database correctly. The console app, however, creates a database with the name along the lines of Namespace.AppContext, which isn't at all what I need. Because of that there is no communication between these projects.
I tried changing Database= to Initial Catalog= in the connection string of the console app, but it didn't change anything.
What can be the cause of this? Can this be happening because the API is logging in via IIS APPPOOL\XYZAC user and the app via WINSRV\Administrator? Seems unlikely, because both have pretty much the same permission groups and access to everything, but I'm not sure what else can be the cause.
What am I doing wrong here?
Edit: I'm sharing the DB models between these two projects. I'll try hard-coding the connection string into the constructor.
Try scaffolding from created xyz database to the console application and see if it connects with the scaffolded context .
Hard-coding the same string like this solved the problem:
public AppContext() : base("Sql n stuff;XYZAC")
Cool. As long as it works, right?

No connection string named "thenameofmyconnection" could be found in the application config file

I am working with entity framework and azure, I got a WCF in a web role which uses methods from the project with entity framework..it seems that I am placing the connection string on the wrong file or that I am defining it wrongly.. it is as follows :
<connectionStrings>
<!-- Windows Azure SQL Database Connection String -->
<add name="AMTEntitiesContainer"
connectionString="here goes my connection string"
providerName="System.Data.EntityClient" />
</connectionStrings>
This is inside my app.config file in my entities library project..should it go to into the config of my webrole? or should it go into my WCF service ?
The connection string should be in the web.config of the WCF service. The EntityFramework project will be executed in-process. The WCF service is the process running.
This could be also helpful to understand these things.
I'm sorry for the post, I can not write comments yet.
If it is the WebService that interact with Azure, you need to move this into its Web.config. If it's the application you have another problem.
I had this,
Simply because I was creating my model incorrectly.
I was incorrectly doing:
var model = new ModelName;
Instead of correctly doing:
var model = ModelName.Create();
So this error may be thrown for a simple reason like that

Retrieve and use Windows Azure's connection strings?

I've configured connection strings in Azure management portal Configure->Connection Strings (linked resources):
What are these connection strings useful for?
I tried deleting the conn. strings from web.config file, so it should read from here, but it doesn't.
Is there any other way?
Basically I want these connection strings to override the connection strings in web.config to be used in production environment.
I've added the following to the Application_Start method:
var sb = new StringBuilder();
var appConfig = ConfigurationManager.OpenMachineConfiguration();
foreach (ConnectionStringSettings conStr in appConfig.ConnectionStrings.ConnectionStrings)
sb.AppendFormat("Name: {0}, ConnectionString: {1}\n", conStr.Name, conStr.ConnectionString);
throw new Exception(sb.ToString());
Here's the result:
Name: LocalSqlServer, ConnectionString: data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true
I tried the above with ConfigurationManager.ConnectionStrings as well and the server (Azure) connection strings were not there.
The connection strings in the Portal allow you to override the connection strings defined in the web.config.
When you're developing locally, you probably use a database located in localhost\SQLExpress or something similar. If you deploy without having set up web.config transformation it would mean that your Web Site running in Windows Azure would still point to localhost\SQLExpress, which isn't something you would want.
The connection strings in the Portal allow you to override existing connection strings which are already defined in the web.config. If your web.config does not contain a connection string with the same name as the one configured in the portal, it will not be added and be accessible at runtime. This might be the issue you're experiencing.
To fix this, simply add a connection string to your web.config file with the same name as the one you have already added to the portal.
Update: Like I already explained in a comment, Windows Azure Web Sites does not physically modify the web.config (source), it does this at runtime. So in order to check which AppSettings and ConnectionStrings are actually available at runtime, try this:
Controller:
public ActionResult Index()
{
ViewBag.ConnectionStrings =
ConfigurationManager.ConnectionStrings.Cast<ConnectionStringSettings>();
ViewBag.AppSettings = ConfigurationManager.AppSettings;
return View();
}
View:
<h3>ConnectionStrings:</h3>
<ul>
#foreach (var setting in ViewBag.ConnectionStrings)
{
<li>#setting.Name: #setting.ConnectionString</li>
}
</ul>
<h3>AppSettings:</h3>
<ul>
#foreach (var s in ViewBag.AppSettings)
{
<li>#setting: #System.Configuration.ConfigurationManager.AppSettings[s]</li>
}
</ul>
After two days, I have finally managed to get it to work. I'm adding my solution here hoping that it might help someone in future.
Environment
Azure API APP (but in theory, it should work for other types of projects too)
SQL DB (hosted on Azure). It can be obviously any db
EF 6.0 - Database First Approach
Connection String is stored on Azure under Application Settings ->Connection Strings section. Image shown below
What I wanted to do
I wanted to put my connection string on Azure and like #Sandrino Di Mattia mentioned, dynamically retrieve it from there.
Steps which worked for me
Create a connectionStrings in the web.config
`
<connectionStrings>
<add name="dbConnectionStringForAzure" connectionString="Local Connection String" providerName="System.Data.EntityClient"/>
</connectionStrings>
`
Note that the providerName is System.Data.EntityClient and not System.Data.SqlClient.
Extra bit: Also, once you have published the project, you can verify that the connection string in the web.config. Navigate to projectorapiurl.scm.azurewebsites.net.
Go to Menu -> Debug Console -> PowerShell -> Edit Web.config file.
(There are other ways to get the web.config files too. Use the one you prefer.)
Note: Here you might find another auto generated connection string by Azure. It's safe to remove that as we aren't using that.
Go to Azure -> your project and Application Settings. Add the details like shown below:
Name = dbConnectionStringForAzure
Value = Provider=System.Data.SqlClient; metadata=res://*/csdlModel.csdl|res://*/ssdlModel.ssdl|res://*/mslModel.msl; Provider Connection String ='Data Source=server.database.windows.net,1433;initial catalog=database;User ID=username;Password=password;MultipleActiveResultSets=True;App=EntityFramework;'
Front the third dropdown, select CUSTOM. It's important else Azure will add System.Data.SqlClient (or any other provider depending upon what is selected) in the provider name of our connection string, which we don't want.
Save
At this stage, Azure should use this connection string on runtime. Want to verify!? do similar to what is suggested above by #Sandrino Di Mattia or in this SO post by #Shaun Luttin Retrieve the connection string of an SQL Azure database that is linked to a Windows Azure Web Site with C#.NET.
Alternatively, put the below code in any razor template:
<p>Value of dbConnectionStringForAzure :
#System.Configuration.ConfigurationManager.ConnectionStrings["dbConnectionStringForAzure"].ConnectionString
</p>
On the other hand, I have set the connection string name in my DbContext constructor.
public MyEntities() : base("name=dbConnectionStringForAzure")
{
}
Now, when I made a call to my API it dynamically used the connection stored in Azure.
Thanks to the dozens of posts and extra shots of coffee!

What is preferred method for modifying connection string settings in DAL class library when deploying asp.net web app?

I deployed my asp.net web app project that has a reference to my DAL class library. How can I change the connection string in my DAL library once deployed? The DAL code was ignoring my web.config connection string and trying to use the app.config value.
I thought I would be able to edit a config file that is associated with the class library, but I can't find one. Temporarily I edited the connection string and re-compiled and re-deployed the library.
Is there an option or way to setup the project files where it changes the values of the connection string based on being compiled in debug mode versus doing a release compile.
What is the recommended way of dealing with connection strings in web apps which reference class libraries?
Clarification:
the DAL library connection strings are also utilized by some datasets and L2S classes (.dbml) and I am not sure how to change those to reference a web.config file that sits outside the library in the web app project.
Currently Using this code to get around my L2S class problem:
public partial class MyDataContext
{
partial void OnCreated()
{
ConnectionStringSettings cs = ConfigurationManager.ConnectionStrings["PrimaryConnectionString"];
if (cs != null)
{
this.Connection.ConnectionString = cs.ConnectionString;
}
}
}
Generally, I let the top-level project define this, via either web.config or app.config; either by specifying that the application should include a connection-string named "FOO", or (much better) allowing the calling application to pass (one of) the connection key, the connection string, or the connection to the dll.
Then you mainly just edit web.config like normal...
I usually place the string in the web.config file and let a class (possibly a global class used to reference settings in the web.config) reference it, with the following line:
class Globals
{
static string ConnectionString =
ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
}
and use it elsewhere like:
IApartmentRepository apartmentRepository = new
ApartmentRepository(Globals.ConnectionString);
This was also Saif Khan's suggestion in his answer.
As for changing the connection strings based on compile mode, Visual Studio 2010 has support for this, see Web Deployment: Web.Config Transformation from the Visual Web Developer team blog. I do not think Visual Studio 2008 can do this out of the box, however maybe it can be done with some kind of build script.
I don't believe there is a recommended way, but a prefered way. Some store connection strings in the web.config file, while some store in the registry or machine.config, while some go to the extreme and store it remotely...yes I've seen that.
The most common storage I see and use myself is storing in the web.config. In my DAL objects I make a call to the web.config file for the connectionstring
string connStr = ConfigurationManager.ConnectionStrings["myString"].ConnectionString
as for auto changing of the connectionstring based on the app compiled mode, I've never seen that. You might have to put that check in the DAL itself to check if debug mode is turned "on" or "off". That would require 2 connectionstring entries in the web.config file.

Categories

Resources