如何在服务堆栈中动态更改sql server连接字符串

时间:2014-03-28 12:28:20

标签: c# asp.net-mvc servicestack ormlite-servicestack servicestack-bsd

我正在研究Asp.Net MVC和ServiceStack。我正在尝试使用servicestack ormlite连接到sql server数据库。喜欢

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

我能够连接到数据库,但在我的场景中,我需要动态更改连接字符串。这意味着我需要从Request主体读取内容并准备连接字符串。在servicestack中,我们在AppHost类中配置sql server连接字符串,这意味着在app start。但我需要在我的控制器中设置连接字符串。 我试过把它放在会话中并在ClassLibrary SeviceBase类中使用该会话。但我无法在类库中使用asp.Net会话。如何在服务堆栈中动态更改sql server连接字符串。所以请指导我。

1 个答案:

答案 0 :(得分:3)

我会更改要在请求范围内重用的IDbConnectionFactory,而不是当前默认值,它在所有请求中共享它。 我还创建了一个静态方法(GetDatabaseConnectionFactory()),它使用自定义连接字符串将OrmLiteConnectionFactory的实例返回给IoC容器。

为了确定连接字符串,我使用了一个请求过滤器,它只读取参数connectionstring。如果未设置,则将使用默认值。那么这个值 在RequestContext.Items集合中设置,可以通过GetDatabaseConnectionFactory()方法访问。

请记住以这种方式公开连接字符串是危险的,请务必彻底检查任何连接字符串值,以确保它们不包含恶意值。 即。确保他们不会尝试连接到管理数据库或其他服务器,或更改默认设置覆盖等。

在你的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;