I'm almost certainly missing something here - but DynamicData is somewhat under-documented and there are lots of assumptions about connection strings (not just in dynamic data) that I have problems with in the real world (where I want to trivially configure same on a per instance basis).
When I had the data model class in the web application there wasn't a problem - data comes from the web.config (well actually from a connections.config) but when I moved the data model into its own class things got interest (i.e. they stopped working)
But... the model has lots of extensibility hooks so I've now got a simple fix for using a custom connection string - still pulled, indirectly, from the app's web.config.
First off lets deal with the location of my connection strings. I play with web applications, these need to work on my local box, in a test instance and in one or more live instances and therefore with multiple connection strings as each has its own database. Similarly other developers will have their own databases. One way to approach this would be to store a connection string per instance - but that can get messy fast - so what you can do is to push bits of a config file out to an external file, so in my web.config you will see the following:
<connectionStrings configSource="connections.config" />
And then the connections.config looks something like:
<connectionStrings>
<add name="MyConnectionString"
connectionString="Data Source=ServerInstance;Initial Catalog=DatabaseName;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
The advantage here - for web applications at least - is that "debug" aside they can be version controlled safely as they are the same everywhere. Then for each deployed instance you have the instance/site specific file which is NOT version controlled and NOT part of the deployed content. Its not perfect... But it works and it makes application updates easy.
So where was I? Oh yes... I can pull the connection string using the standard configuration methods easily enough - but how can I persuade the DataContext to use it? After all when you set up the model you have no mechanism to tell it the context string so its going to make assumptions based on your model and for my solutions those assumptions are going to be wrong.
Well the answer is that the generated DataContext class is partial and that one of the hooks put in is an OnCreated method - and that we can use to set our connection string.
So we add the following to the DataContext class :
public static string ConnectionString { get; set; }
partial void OnCreated()
{
if (!string.IsNullOrEmpty(ConnectionString))
{
this.Connection.ConnectionString = ConnectionString;
}
}
Note that 1) I'm (hopefully) ensuring that we get the default behaviour if we don't explicitly set the connection string and 2) the connection will be the same for all instances even if you use the constructor that explicitly sets the connection string... However given that you're setting the connection string "globally" I would expect that in most cases you won't need to do that any more.
Then, before you do model.RegisterContext in global.asax.cs, you just (!) need to set the connection string:
string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
MyDataClassesDataContext.ConnectionString = connStr;
And that should pretty much be that. When an instance of the DataContext is initiaised the OnCreated method overrides the connection string with the value that was set at startup and all should, hopefully, be well!
A perhaps slightly better other option might be to subclass the DataContext class and override the default constructor to get similar behaviour - but you still want to use a property as above to avoid having to wire and understanding of config into your DataContext class.
Comments