I just got had by an odd behavior in the LINQ to SQL model designer when working with a LINQ to SQL Model in a separate class library project. I use LINQ to SQL in a business layer which always lives in a separate assembly and so the model does not live in the same project as the Web (or other) application I'm working on.
When the model is created the DataContext has options on how the Connection is handled when you create your DataContext without specifying any parameters in the constructor - ie. you're instantiating the DataContext without a connection string or connection object:
TimeTrakkerContext context = new TimeTrakkerContext();
When you do this the settings are read from the configuration settings or the default connection string if no settings are available. You can see these settings in the DataContext properties under Connection:
You can specify a default connection string, and whether you like to use Application Settings to read the value from your config file.
Now the behavior for this is different depending in which type of project you LINQ to SQL. If you use a Web Project the Application settings are directly read from the ConfigurationManager object:
public DataClassesDataContext() :
base(global::System.Configuration.ConfigurationManager.ConnectionStrings["TimeTrakkerConnectionString"].ConnectionString, mappingSource)
{
OnCreated();
}
This directly maps to the plain ConnectionStrings key specified as you would expect.
If you however use the model in a class library project you get code that maps to the Settings object:
public TimeTrakkerContext() :
base(global::TimeTrakker.Properties.Settings.Default.TimeTrakkerConnectionString, mappingSource)
{
OnCreated();
}
and which is set up like this:
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=.;Initial Catalog=TimeTrakker;Integrated Security=True")]
public string TimeTrakkerConnectionString {
get {
return ((string)(this["TimeTrakkerConnectionString"]));
}
}
This is important for a couple of reasons: First using the Model in a class library project requires that you use this configuration settings class so you can't toss it as I often do in my projects. The compiler will let you know if you do and the model will recreate it for you. Heavy handed this, but I can live with that I suppose.
But maybe more confusing is the fact that even though I specify TimeTrakkerConnectionString as my key name the actual key that the DataContext is looking for is more complex - it's the full typename (namespace.class.key) when it actually is stored in the app.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="TimeTrakker.Properties.Settings.TimeTrakkerConnectionString"
connectionString="Data Source=.;Initial Catalog=TimeTrakker_Westwind;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
Not paying real close attention to the key created in App.Config I just created an entry for JUST TimeTrakkerConnectionString in my web.config file - only to find that the connection string was not respected at all.
It took a while of a going back and forth staring - and missing - the obvious to actually figure out that the damn key wasn't just TimeTrakkerConnectionString but the whole nine yards of TimeTrakker.Properties.Settings.TimeTrakkerConnectionString. Grumble, grumble, grumble...
Now, the ConnectionString key is only used if you use the default parameterless constructor on the DataContext. As an alternative you can also pass an explict connection string and if you want to avoid the business of having Application Settings generated just set the ConnectionString to None. This will cause the DataContext to be generated without the parameterless constructor and you have to pass a connection string instead. You can then subclass the DataContext (or use a wrapper like I do with the business object) to handle passing an application level connection string from whatever source you prefer.
However, having the default ConnectionString value there is nice because it makes it easier to write quick sample queries to test operation.
Other Posts you might also like