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

发布于 2024-10-16 12:40:53 字数 2562 浏览 0 评论 0原文

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

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

我使用 Subsonic 2.x 作为数据访问层。 在管理网站中,我必须将所有连接字符串放在

<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

I created my own CMS for my own use.
currently, I already launch 3 websites using my CMS. and will keep adding.

since all the websites always use the same version of my CMS, I just need to create one administration site to rule them all.

I use Subsonic 2.x for data access layer.
in administration website, I have to put all 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>

here is the ugly code

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;
}

I'm looking for a way to make it like this

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

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

Is there any ORM solution that support this?

Or,

do you know any workaround to do it with current ORM (Subsonic 2.x) ?

UPDATE: I add one more example

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

总以为 2024-10-23 12:40:53

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

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

If you only need to manage the CMS for one site at once, I would use a single SubSonic provider, and change the static DefaultConnectionString property, as per this example:

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

儭儭莪哋寶赑 2024-10-23 12:40:53

我不知道亚音速,但在 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;
    }
}

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

I don't know about subsonic, but in LINQ-to-SQL you could write a ContextFactory which creates contexts using different connection strings.

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;
    }
}

The connection string itself you could either hard code or read from a config file, or from whereever you want :-)

顾铮苏瑾 2024-10-23 12:40:53

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

如果是第一种情况(当您的应用程序启动时):
我不知道 Subsonic,但 NHibernate 可以做到这一点。

var cfg = new Configuration();

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

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

What exactly do you want?
Set the connection string once (but programmatically) when your application starts?
Or do you want to change the connection string while your app is running, like "run only the next query on database number two"?

If it's the first case (once when your application starts):
I don't know Subsonic, but NHibernate can do this.

var cfg = new Configuration();

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

cfg.AddAssembly( ... );
ISessionFactory sf = cfg.BuildSessionFactory();
感受沵的脚步 2024-10-23 12:40:53

既然您的所有 ConnectionStrings 都保存在 web.config 文件中,为什么不直接从 connectionStrings Collection 中获取适合您当前网站的名称呢?

ConfigurationManager.ConnectionStrings[sitename].ConnectionString;

或者

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

SELECT connection FROM tblConnections WHERE siteName = 'first'

希望这有帮助。

since all your ConnectionStrings saved in the web.config file, why not just take what suitable your current website name from the connectionStrings Collection directly?

ConfigurationManager.ConnectionStrings[sitename].ConnectionString;

OR

save the connections back in a database (you may need encryption here to keep yourself safe)
so you dont hardcoded them in the web.config and you just store the connection of that database, now .. one query could solve the whole issue by filtering on the website name - a small logic class can do this for you

SELECT connection FROM tblConnections WHERE siteName = 'first'

Hope this helped.

我不吻晚风 2024-10-23 12:40:53

您本质上要求的是一个多租户应用程序。

使用相同业务逻辑和用户界面的相同应用程序(您的 CMS)将会有所不同,具体取决于您所操作的客户端/上下文/公司/租户

在您的情况下,您正在执行“单一应用程序、隔离数据库”多租户。也就是说,您有一个应用程序,每个租户都有自己的数据库,与其他租户隔离。 (其他选项包括共享数据库,其中使用键(例如所有表上的“TENANT_ID”)隔离记录,并使用 where 子句将它们过滤掉)。

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

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

对于 SubSonic,我相信你也可以做多个数据库 - 但在它们之间交换是我不知道如何做的事情。

What you're essentially asking for is a multi-tenanted application.

The same application (your CMS) using the same business logic and user interface will be different depending upon which client/context/company/tenant you're operating on.

In your situation you're doing 'single application, isolated database' multi-tenancy. That is you have a single app, and each tenant has their own database, isolated from the other tenants. (Other options include a shared database where records are isolated using a key, such as "TENANT_ID" on all tables, and the where clause filters them out).

In NHibernate you can achieve this by using multiple session factories (one per tenant) identified by a unique identifier, such as the site id.

Working out which site id to use can be done in a number of ways. Our application bases it off the hostname, but if you're doing it from a single site, but wanting to switch contexts you could do it as a form field from a dropdown box of "site selector".

For SubSonic I believe you can do multiple databases as well - but swapping between them is something I don't know how to do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文