任何 ORM 都可以在运行时以编程方式更改其连接字符串吗?
我创建了自己的 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 技术交流群。

发布评论
评论(5)
我不知道亚音速,但在 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;
}
}
连接字符串本身您可以硬编码或从配置文件中读取,或者从您想要的任何地方读取:-)
你到底想要什么?
当应用程序启动时设置一次连接字符串(但以编程方式)?
或者您想在应用程序运行时更改连接字符串,例如“仅在第二个数据库上运行下一个查询”?
如果是第一种情况(当您的应用程序启动时):
我不知道 Subsonic,但 NHibernate 可以做到这一点。
var cfg = new Configuration();
// set connectionstring programmatically
cfg.Properties["connection.connection_string"] = getConnectionString(sitename);
cfg.Configure();
cfg.AddAssembly( ... );
ISessionFactory sf = cfg.BuildSessionFactory();
既然您的所有 ConnectionStrings
都保存在 web.config
文件中,为什么不直接从 connectionStrings Collection
中获取适合您当前网站的名称呢?
ConfigurationManager.ConnectionStrings[sitename].ConnectionString;
或者
将连接保存回数据库(您可能需要在此处加密以确保自己的安全)
因此,您不必在 web.config
中对它们进行硬编码,而只需存储该数据库的连接,现在..一个查询可以通过过滤网站名称来解决整个问题 - 一个小逻辑类可以为你做到这一点
SELECT connection FROM tblConnections WHERE siteName = 'first'
希望这有帮助。
您本质上要求的是一个多租户应用程序。
使用相同业务逻辑和用户界面的相同应用程序(您的 CMS)将会有所不同,具体取决于您所操作的客户端/上下文/公司/租户。
在您的情况下,您正在执行“单一应用程序、隔离数据库”多租户。也就是说,您有一个应用程序,每个租户都有自己的数据库,与其他租户隔离。 (其他选项包括共享数据库,其中使用键(例如所有表上的“TENANT_ID”)隔离记录,并使用 where 子句将它们过滤掉)。
在 NHibernate 中,您可以通过使用由唯一标识符(例如站点 ID)标识的多个会话工厂(每个租户一个)来实现此目的。
可以通过多种方式确定要使用的站点 ID。我们的应用程序基于主机名,但如果您从单个站点执行此操作,但想要切换上下文,则可以将其作为“站点选择器”下拉框中的表单字段来执行。
对于 SubSonic,我相信你也可以做多个数据库 - 但在它们之间交换是我不知道如何做的事情。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如果您只需要一次管理一个站点的 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