How can i tell SubSonic 2 to use a different .config file?

Learn how can i tell subsonic 2 to use a different .config file? with practical examples, diagrams, and best practices. Covers .net, subsonic, app-config development techniques with visual explanat...

Configuring SubSonic 2 to Use a Custom Configuration File

Hero image for How can i tell SubSonic 2 to use a different .config file?

Learn how to direct SubSonic 2.x to load its database connection settings from an alternative .config file, enabling flexible deployment and environment-specific configurations.

SubSonic 2.x, a popular ORM for .NET, typically relies on the standard app.config or web.config file for its database connection string. However, in scenarios requiring dynamic environments, multi-tenant applications, or simply better separation of concerns, you might need SubSonic to read its configuration from a different file. This article will guide you through the process of overriding Sub SubSonic's default behavior to specify a custom configuration file.

Understanding SubSonic's Configuration Mechanism

By default, SubSonic 2.x uses the System.Configuration.ConfigurationManager class to retrieve connection strings. This class is designed to read from the application's primary configuration file (App.config for desktop apps, Web.config for web apps). To make SubSonic look elsewhere, we need to intercept or modify how it accesses these settings. The key is to leverage the SubSonic.DataService.Provider property, which allows us to programmatically define the connection string or even the entire provider.

flowchart TD
    A[Application Start] --> B{SubSonic Init}
    B --> C{Default: Read app.config/web.config}
    C --> D[Use Connection String]
    B --> E{Custom Config Logic}
    E --> F[Load Custom .config File]
    F --> G[Extract Connection String]
    G --> H[Set SubSonic.DataService.Provider]
    H --> D

Flowchart illustrating SubSonic's default and custom configuration paths.

Method 1: Programmatically Setting the Connection String

The most straightforward way to tell SubSonic to use a different connection string is to set it directly in your application's startup code. This involves reading your custom configuration file manually and then assigning the connection string to SubSonic.DataService.Provider.DefaultConnectionString.

using System.Configuration;
using System.IO;
using SubSonic.DataProviders;

public static class SubSonicConfig
{
    public static void InitializeSubSonic(string configFilePath)
    {
        // Load the custom configuration file
        ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configFilePath;
        Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

        // Get the connection string from the custom config
        ConnectionStringSettings connectionStringSetting = config.ConnectionStrings.ConnectionStrings["MyCustomConnection"];

        if (connectionStringSetting != null)
        {
            // Set the default connection string for SubSonic
            DataService.GetInstance("MyCustomConnection").DefaultConnectionString = connectionStringSetting.ConnectionString;
            // Or, if you want to set the global default:
            // DataService.DefaultConnectionString = connectionStringSetting.ConnectionString;

            // You might also need to set the provider type if it's not the default
            // DataService.GetInstance("MyCustomConnection").DefaultProvider = ProviderFactory.GetProvider(connectionStringSetting.ProviderName);
        }
        else
        {
            throw new ConfigurationErrorsException($"Connection string 'MyCustomConnection' not found in {configFilePath}");
        }
    }
}

// Example usage in your application startup (e.g., Global.asax or Program.cs)
// string customConfigFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomSettings.config");
// SubSonicConfig.InitializeSubSonic(customConfigFile);

C# code to load a connection string from a custom configuration file and apply it to SubSonic 2.x.

Method 2: Using a Custom SubSonic Provider (Advanced)

For more complex scenarios, you might consider creating a custom IDataProvider implementation. This allows you to completely control how SubSonic retrieves its settings, including connection strings, and even how it interacts with the database. While more involved, it offers maximum flexibility.

using System.Configuration;
using SubSonic.DataProviders;
using SubSonic.SqlGeneration.Schema;

public class CustomConfigDataProvider : SqlDataProvider
{
    public CustomConfigDataProvider(string connectionString, string providerName)
        : base(connectionString, providerName)
    {
        // You can add custom logic here if needed
    }

    // Override methods if you need to customize behavior beyond just the connection string
    // For example, if you want to dynamically change the connection string based on context
    // public override string ConnectionString
    // {
    //     get { return GetDynamicConnectionString(); }
    // }
}

// To use this:
// In your application startup:
// string customConfigFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomSettings.config");
// ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
// fileMap.ExeConfigFilename = customConfigFile;
// Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
// ConnectionStringSettings connectionStringSetting = config.ConnectionStrings.ConnectionStrings["MyCustomConnection"];

// if (connectionStringSetting != null)
// {
//     IDataProvider customProvider = new CustomConfigDataProvider(
//         connectionStringSetting.ConnectionString,
//         connectionStringSetting.ProviderName
//     );
//     DataService.Set  // Note: SubSonic 2.x might require a different approach to register custom providers globally
//     // You might need to set it for a specific repository or use DataService.GetInstance("MyCustomConnection").DefaultProvider = customProvider;
// }

Example of a custom SubSonic data provider, offering advanced configuration control.

Deployment Considerations

When deploying your application, ensure that your custom configuration file is present in the application's output directory. For web applications, this might mean placing it in the root directory or a specific subfolder. For desktop applications, it should reside alongside the executable. Always consider how you will manage these custom configuration files across different environments (development, staging, production) to avoid manual errors.

1. Create Custom Configuration File

Create a new XML file (e.g., CustomSettings.config) in your project and ensure its 'Copy to Output Directory' property is set to 'Copy always' or 'Copy if newer'.

2. Add Connection String

Populate CustomSettings.config with your desired connection string, formatted like a standard connectionStrings section.

3. Implement Initialization Logic

Add the C# code from Method 1 to your application's startup routine (e.g., Global.asax.cs for web apps, Program.cs for console/desktop apps).

4. Call Initialization Method

Invoke your InitializeSubSonic method with the path to your custom configuration file before any SubSonic data access occurs.

5. Test Thoroughly

Run your application and verify that SubSonic is successfully connecting to the database using the connection string from your custom file.