views:

213

answers:

4

Hey all,

I have an application that does projection of data for my client over a length of time. In order to allow the client to 'play' w/ other scenarios w/o messing up production data, they are able to choose alternative databases (basically What-If scenarios) at any point, which are a copy of the production database as of a given time. Currently, I have bit of code in place that basically does a string replacement on the connection string, which will hot-swap the server name and database name, based on the user's selection stored in the session state.

This approach works well for what I am doing, although it does require me to pass around those selections throughout every layer. Here is my question: I would like to be able to create a custom connection string that would handle this 'switching' in the background and allow me to use a connection string just like I do in a standard Asp.Net application.

In other words, many asp.net tools accept just a connection string name as part of their constructor. I would like to be able to utilize those tools, but cannot do so b/c of the way I currently build my connection string. Is there a way to support this behavior on a user session level?

A: 

It seems as if you could just name your connection strings significantly, then pass around that significant name: Production, Test, Etc.

Your web.config could have all the connection strings in it, then you just retrieve the connection string based on the name.

<add name="Production" connectionString="Database=Widgets;Server=SQL-PROD;Trusted_Connection=yes" />
<add name="Test" connectionString="Database=AltWidgets;Server=SQL-TEST;Trusted_Connection=yes" />

When you make your connection, just pass it:

SqlConnection conn = new conn(ConfigurationManager.ConnectionStrings[Session["SelectedDB"]].ToString());
JustLoren
I have considered this approach, however, the process of spawning a "what if" is out of my control and I would like to avoid having to manually add these settings for every spawn. This is a good approach though and I am keeping it as my last resort.
Nathan
A: 

You could create a custom object, override the ToString method, and pass myObject.ToString() in as the parameter for those objects, eg.

class CustomObject
{
    override public string ToString()
    {
         // In here would go whatever logic you use to decide 
         // which conn string should be returned
         return "Data Source=server; User ID=user; Password=password;" + 
                   "Initial Catalog=" + Session["DBName"];
    }
}

Then to use it:

CustomObject co = new CustomObject();
SqlConnection conn = new SqlConnection(co.ToString());
A S
This is very similiar to the approach that I am doing now. Unfortunately, I don't think it will work w/ the current situation. Many objects accept a Connection String Name (as opposed to the connection string) as a parameter, which basically puts it out of my control.
Nathan
You could do the same thing, but instead of returning a connection string, return a connection string name?What sort of objects are you referring to that accept the conn string name? Are these custom objects or built in ASP.Net controls?
A S
They are asp.net controls, such as the Asp.Net SqlCacheDependency Object, which accepts a registered Name in the schema (which then refers to a connection string name). If I did the same thing w/ the connection string name, I would have to have each instance of connection string registered in the web.config, rather than being dynamic. This is much like JustLoren's suggestion.
Nathan
Can't think of anything off the top of my head. This might be of some use:http://stackoverflow.com/questions/158783/is-there-a-way-to-override-configurationmanager-appsettings
A S
You can also use an SqlCommand object to create a CacheDependency, which would be easier to change dynamically, but that of course wouldn't help for other objects where you can't do that.
A S
Yeah, I had to abandon the other constructor due to limitations of SQL Cache Dependecy and allowing it to "infer" the depenecies from the query. Thanks though!
Nathan
A: 

I think System.Data.SqlClient.SqlConnectionStringBuilder will be perfect for your needs.

Ian Kemp
This is very similar to my current implementation, however, it does not match my current need. Basically, I am trying to use controls that accept a Connection String Name as part of their constructor, which takes the building portion of the connection string out of my hand. I would like to override the default building process to suit my own ends, but I am not sure how this can be done. Does that make sense?
Nathan
A: 

There's a number of different ways of dealing with this.

Some people have complete separate copies of their web.config files (where the connection string(s) should be kept) and using post-build events, they can copy a relevant web.config file based upon the "release configuration" you're using in Visual Studio.

This method has been blogged about by Scott Gu, and also others.
Also, see this StackOverflow question:
How do you deal with connection strings when deploying an ASP.NET site?

Now, the above is are great methods when initially deploying your ASP.NET application, however, if you want to do this when the application is already deployed, you can use this handy mechanism: ConnectionString Trick

It does sound like you're doing something very similar to this already, and if you want to be able to dynamically switch databases at runtime, I think the best you can do is to just "switch" connection strings within your code. Of course, the trick here is to simplify this so that only one place in your application is responsible for providing a database connection string to the rest of your application.

Probably the best way to handle this is to ensure that all values you wish to retrieve from the web.config are retrieved using a class that derives from the System.Configuration.ConfigurationSection class. This will allow you to encapsulate any logic (such as the "connection string-based-on-machine-name" trick above) required to "switch" the actual value returned in one place, and allow you to use your custom class's "connectionstring" property in any other component's constructor that requires a connectionstring as a parameter, without having to change this when the actual connection string value changes.

Some good resources for custom Configuration Sections are:

How to: Create Custom Configuration Sections Using ConfigurationSection
Creating Custom Configuration Sections in Web.config Using .NET 2.0's Configuration API
Custom Configuration Sections in 3 Easy Steps

CraigTP
Thanks for the informative comment! I am aware of the Connection String Trick, however, my case is just a little bit different. I need a different connection string based on the user and, potentially, their selections of which database they want the application to target. In other words, it is not simply a deployment switch or a setting that I can set during Application_Start.Making a custom configuration section would be perfect, IF I could override the current Connection String configuration section with my own. I am looking for information to do so, but not pulling anything yet.
Nathan