我已经提出了我自己的(可能是非常规的)解决方案来解决这个问题。我们为许多不同的客户开发了许多不同的 Web 项目,并且由于我们在多个 web.config 文件中遇到的所有问题,或者在发布前需要进行编辑,因此将它们全部迁移到这种方法。
基本上,我们让我们的应用根据传入的 URL 告诉我们它在哪个环境下运行。我们在第一个请求时对其进行初始化,并将其存储在应用程序生命周期的内存中。通过这种方式,我们可以将每个环境特定的配置值存储在同一个配置文件中,并使用 Development、Staging、Production 等对其进行限定。任何在环境之间没有差异的设置都不需要限定。
首先是一个示例 web.config:
<appSettings>
<add key="DevelopmentHost" value="dev.trackmyhours.com" />
<add key="StagingHost" value="staging.trackmyhours.com" />
<add key="ProductionHost" value="www.trackmyhours.com" />
</appSettings>
<connectionStrings>
<clear />
<add name="DevelopmentConnectionString" connectionString="your dev conn string" providerName="System.Data.SqlClient" />
<add name="StagingConnectionString" connectionString="your staging conn string (mine is typically same as staging)" providerName="System.Data.SqlClient" />
<add name="ProductionConnectionString" connectionString="your production conn string" providerName="System.Data.SqlClient" />
</connectionStrings>
接下来我们有一个“App”类,它使我们能够访问我们的“Site”类,但是您可以按照您认为合适的方式构建您的类。
Public Class App
Private Shared _Site As New Site
Public Shared ReadOnly Property Site() As Site
Get
Return _Site
End Get
End Property
End Class
Imports System.Configuration
Imports System.Web
Public Class Site
Public Enum EnvironmentType
Development
Staging
Production
End Enum
Friend Sub New()
If HttpContext.Current IsNot Nothing Then
Dim URL = HttpContext.Current.Request.Url.DnsSafeHost
Select Case URL
Case ConfigurationManager.AppSettings("DevelopmentHost"), "localhost"
_Environment = EnvironmentType.Development
Case ConfigurationManager.AppSettings("StagingHost")
_Environment = EnvironmentType.Staging
Case ConfigurationManager.AppSettings("ProductionHost")
_Environment = EnvironmentType.Production
End Select
Else
'probably getting called from a winforms/console app, or unit tests
_Environment = EnvironmentType.Staging
End If
_ConnectionString = ConfigurationManager.ConnectionStrings(_Environment.ToString & "ConnectionString").ConnectionString
End Sub
Private _Environment As EnvironmentType
Public Property Environment() As EnvironmentType
Get
Return _Environment
End Get
Set(ByVal value As EnvironmentType)
_Environment = value
_ConnectionString = ConfigurationManager.ConnectionStrings(_Environment.ToString & "ConnectionString").ConnectionString
End Set
End Property
Private _ConnectionString As String
Public ReadOnly Property ConnectionString() As String
Get
Return _ConnectionString
End Get
End Property
End Class
我们将类放入 Biz Object 类库中。我们刚刚决定不必确定每个请求的环境,因为它在应用程序的生命周期内确实无法更改。此外,这允许我们在库中的代码或后面的代码中从 ANYWHERE 引用 App.Site.Environment。如果您需要在代码中添加一些条件逻辑,这也很有帮助 - 例如在 dev/staging 中运行时不向真实的人发送电子邮件。
最后一件事 - 对于我们的 Linq2SQL 或 EF Data/ObjectContexts,我们不会将连接字符串存储在文件中,而是重载构造函数,以便我们可以像这样提供正确的环境连接字符串:
Partial Class SampleDataContext
Sub New()
MyBase.New(App.Site.ConnectionString)
End Sub
End Class