Question

I am working on Asp.Net MVC and ServiceStack. I am trying to connect to the sql server database using servicestack ormlite. like

 var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
 container.Register<IDbConnectionFactory>(
 new OrmLiteConnectionFactory(connectionString,
                    SqlServerOrmLiteDialectProvider.Instance)
                {
                    ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current)
                });

I am able to connect to database, But in my scenario i need to change the connection string dynamically.. That means i need to read the content from Request body and prepare a connection string. In servicestack we configure sql server connection string in AppHost class that means at app start. But i need to set the connection string in my controller. I have tried like place it in session and use that session in ClassLibrary SeviceBase class. But I am unable to use asp.Net sessions in class libraries.How to change sql server connection string dynamically in service stack. so please guide me.

Was it helpful?

Solution

I would change the IDbConnectionFactory to be reused in the scope of the request, instead of the current default, which shares it among all requests. I have also created a static method (GetDatabaseConnectionFactory()) which returns the instance of OrmLiteConnectionFactory to the IoC container with the custom connection string.

To determine the connection string, I have used a request filter, which simply reads the parameter connectionstring. If it is not set it will use a default value. This value is then set in the RequestContext.Items collection, which can be accessed by the GetDatabaseConnectionFactory() method.

Remember exposing connection strings this way is dangerous, always check any connection string values thoroughly to ensure they don't contain malicious values. i.e. Ensure they don't try to connect to administrative databases, or a different server, or change default setting overrides etc.

In your AppHost:

ServiceStack V3:

public override void Configure(Container container)
{
    container.Register<IDbConnectionFactory>(c => GetDatabaseConnectionFactory()).ReusedWithin(ReuseScope.Request);

    RequestFilters.Add((req,res,obj) => {
        // Default value
        var defaultConnectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;

        // Get the connection string from the connectionstring parameter, or use default
        var dbConnectionString = req.GetParam("connectionstring") ?? defaultConnectionString;

        // You should perform some checks here to make sure the connectionstring isn't something it shouldn't be
        // ...

        // Save the connection string to the HostContext.Instance.Items collection, so we can read it later
        HostContext.Instance.Items.Add("ConnectionString", dbConnectionString);
    });
}

public static IDbConnectionFactory GetDatabaseConnectionFactory()
{
    // Read the connection string from our HostContext Items
    var dbConnectionString = HostContext.Instance.Items["ConnectionString"];

    if(dbConnectionString == null)
        throw new Exception("Connection string has not been set");

    // Return the connection factory for the given connection string
    return new OrmLiteConnectionFactory(dbConnectionString, SqlServerOrmLiteDialectProvider.Instance) {
        ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current)
    });
}

Usings:

using System;
using Funq;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceHost;
using ServiceStack.WebHost.Endpoints;
using ServiceStack.OrmLite;
using ServiceStack.Common;

ServiceStack V4:

public override void Configure(Container container)
{
    container.Register<IDbConnectionFactory>(c => GetDatabaseConnectionFactory()).ReusedWithin(ReuseScope.Request);

    GlobalRequestFilters.Add((req,res,obj) => {
        // Default value
        var defaultConnectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;

        // Get the connection string from the connectionstring parameter, or use default
        var dbConnectionString = req.GetParam("connectionstring") ?? defaultConnectionString;

        // You should perform some checks here to make sure the connectionstring isn't something it shouldn't be
        // ...

        // Save the connection string to the RequestContext.Items collection, so we can read it later
        HostContext.RequestContext.Items.Add("ConnectionString", dbConnectionString);
    });
}

public static IDbConnectionFactory GetDatabaseConnectionFactory()
{
    // Read the connection string from our Items
    var dbConnectionString = HostContext.RequestContext.Items["ConnectionString"];

    if(dbConnectionString == null)
        throw new Exception("Connection string has not been set");

    // Return the connection factory for the given connection string
    return new OrmLiteConnectionFactory(dbConnectionString, SqlServerOrmLiteDialectProvider.Instance) {
        ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current)
    });
}

Usings:

using System;
using Funq;
using ServiceStack;
using ServiceStack.Data;
using ServiceStack.OrmLite;
using ServiceStack.OrmLite.Sqlite;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top