任何 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)
如果您只需要一次管理一个站点的 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
我不知道亚音速,但在 LINQ-to-SQL 中,您可以编写一个 ContextFactory,它使用不同的连接字符串创建上下文。
连接字符串本身您可以硬编码或从配置文件中读取,或者从您想要的任何地方读取:-)
I don't know about subsonic, but in LINQ-to-SQL you could write a ContextFactory which creates contexts using different connection strings.
The connection string itself you could either hard code or read from a config file, or from whereever you want :-)
你到底想要什么?
当应用程序启动时设置一次连接字符串(但以编程方式)?
或者您想在应用程序运行时更改连接字符串,例如“仅在第二个数据库上运行下一个查询”?
如果是第一种情况(当您的应用程序启动时):
我不知道 Subsonic,但 NHibernate 可以做到这一点。
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.
既然您的所有
ConnectionStrings
都保存在web.config
文件中,为什么不直接从connectionStrings Collection
中获取适合您当前网站的名称呢?或者
将连接保存回数据库(您可能需要在此处加密以确保自己的安全)
因此,您不必在
web.config
中对它们进行硬编码,而只需存储该数据库的连接,现在..一个查询可以通过过滤网站名称来解决整个问题 - 一个小逻辑类可以为你做到这一点希望这有帮助。
since all your
ConnectionStrings
saved in theweb.config
file, why not just take what suitable your current website name from theconnectionStrings Collection
directly?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 youHope this helped.
您本质上要求的是一个多租户应用程序。
使用相同业务逻辑和用户界面的相同应用程序(您的 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.