任何ORM都可以在运行时以编程方式更改其连接字符串?

时间:2011-02-07 13:21:09

标签: c# orm subsonic

我创建了自己的CMS供我自己使用。 目前,我已经使用我的CMS推出了3个网站。并将继续添加。

由于所有网站都使用相同版本的CMS,因此我只需要创建一个管理网站来统治它们。

我使用Subsonic 2.x作为数据访问层。 在管理网站,我必须把所有connectionStrings

<SubSonicService defaultProvider="firstSql">
    <providers>
        <clear/>
        <add name="firstSql" type="SubSonic.SqlDataProvider, SubSonic" connectionStringName="first" generatedNamespace="firstSql"/>
        <add name="secondSql" type="SubSonic.SqlDataProvider, SubSonic" connectionStringName="second" generatedNamespace="second"/>
        <add name="thirdSql" type="SubSonic.SqlDataProvider, SubSonic" connectionStringName="third" generatedNamespace="thirdSql"/>
    </providers>
</SubSonicService>

<connectionStrings>
    <clear/>
    <add name="first" connectionString="Data Source=123.123.12.3;Initial Catalog=first;User ID=first;Password=first" providerName="System.Data.SqlClient"/>
    <add name="second" connectionString="Data Source=123.123.12.3;Initial Catalog=second;User ID=second;Password=second" providerName="System.Data.SqlClient"/>
    <add name="third" connectionString="Data Source=123.123.12.3;Initial Catalog=third;User ID=third;Password=third" providerName="System.Data.SqlClient"/>
</connectionStrings>

这是丑陋的代码

switch(sitename){
    case "first":
        var comment1 = new firstSql.Comment(id);
        comment1.Accepted = true;
        comment1.Save();
        break;
    case "second":
        var comment2 = new secondSql.Comment(id);
        comment2.Accepted = true;
        comment2.Save();
        break;
    case "third":
        var comment3 = new thirdSql.Comment(id);
        comment3.Accepted = true;
        comment3.Save();
        break;
}

我正在寻找一种方法让它像这样

/* some magic to dynamically change the connection string */
cmsSql.ConnectionString( getConnectionString(sitename) ); 

var comment = new cmsSql.Comment(id);
comment.Accepted = true;
comment.Save();

是否有支持此功能的ORM解决方案?

或者,

您知道使用当前ORM(Subsonic 2.x)做任何解决方法吗?

更新:我再添加一个例子

cmsSql.ConnectionString( DB_ConString_WebsiteABC ); 

var comment = new cmsSql.Comment(id);
comment.Accepted = true;
comment.Save();

/* some magic to dynamically change the connection string */
cmsSql.ConnectionString( DB_ConString_AnotherWebsiteThatSimilarToABC ); 

var comment = new cmsSql.Comment(id);
comment.Accepted = true;
comment.Save(); // saved to another database

5 个答案:

答案 0 :(得分:1)

我不知道亚音,但在LINQ-to-SQL中你可以编写一个ContextFactory,它使用不同的连接字符串创建上下文。

static class ContextFactory
{
    public static MyDataContext CreateMyDataContent(string sitename)
    {
        var context;
        switch(sitename){
        case "first":
            context = new MyDataContext ("connection string");
        case "second":
            // and so on
        }

        return context;
    }
}

连接字符串本身你可以硬编码或从配置文件读取,或从你想要的任何地方读取: - )

答案 1 :(得分:1)

如果您只需要同时管理一个站点的CMS,我将使用单个SubSonic提供程序,并根据此示例更改静态DefaultConnectionString属性:

http://www.stevetrefethen.com/blog/SettingSubsonicsconnectionstringatruntime.aspx

答案 2 :(得分:0)

你到底想要什么?
在应用程序启动时设置连接字符串一次(但以编程方式)? 或者,您是否希望在应用程序运行时更改连接字符串,例如“仅运行第二个数据库的查询”?

如果是第一种情况(一次申请开始时):
我不知道Subsonic,但NHibernate可以做到这一点。

var cfg = new Configuration();

// set connectionstring programmatically
cfg.Properties["connection.connection_string"] = getConnectionString(sitename);
cfg.Configure();

cfg.AddAssembly( ... );
ISessionFactory sf = cfg.BuildSessionFactory();

答案 3 :(得分:0)

由于您在ConnectionStrings文件中保存了所有web.config,为什么不直接从connectionStrings Collection获取适合您当前网站名称的内容?

ConfigurationManager.ConnectionStrings[sitename].ConnectionString;

OR
将连接保存回数据库(您可能需要加密以保证自己的安全) 所以你不要在web.config硬编码它们,你只需存储该数据库的连接,现在..一个查询可以通过过滤网站名称解决整个问题 - 一个小逻辑类可以做到这一点您

SELECT connection FROM tblConnections WHERE siteName = 'first'

希望这会有所帮助。

答案 4 :(得分:0)

您基本上要求的是多租户申请。

使用相同业务逻辑和用户界面的相同应用程序(您的CMS)将根据您正在操作的客户/上下文/公司/ 租户而有所不同。

在您的情况下,您正在进行'单一应用程序,隔离数据库'多租户。那就是你有一个应用程序,每个租户都有自己的数据库,与其他租户隔离。 (其他选项包括使用密钥隔离记录的共享数据库,例如所有表上的“TENANT_ID”,以及where子句将其过滤掉)。

在NHibernate中,您可以通过使用由唯一标识符(例如站点ID)标识的多个会话工厂(每个租户一个)来实现此目的。

确定要使用的网站ID可以通过多种方式完成。我们的应用程序基于主机名,但如果您是从单个站点进行操作,但想要切换上下文,则可以从“站点选择器”的下拉框中将其作为表单域进行。

对于SubSonic我相信你也可以做多个数据库 - 但是在他们之间交换我不知道该怎么做。