如何使基于NServiceBus主机的windows服务等待SQL Server启动?
我在与包含订阅存储数据库的SQL server实例相同的服务器上安装了多个NServiceBus通用基于主机的windows服务。当服务器启动时,my NServiceBus主机服务尝试在SQL server启动之前访问订阅存储数据库 以下是我迄今为止所尝试的:如何使基于NServiceBus主机的windows服务等待SQL Server启动?,nservicebus,Nservicebus,我在与包含订阅存储数据库的SQL server实例相同的服务器上安装了多个NServiceBus通用基于主机的windows服务。当服务器启动时,my NServiceBus主机服务尝试在SQL server启动之前访问订阅存储数据库 以下是我迄今为止所尝试的: 在MSSQLSERVER上添加了windows服务器依赖项。这并没有解决问题 在IWantCustomInitialization.Init中添加了1分钟睡眠,以验证上述问题的原因。这解决了问题,但这是一个非常粗糙的解决方案 处理此问题
<DBSubscriptionStorageConfig>
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider"/>
<add Key="connection.driver_class" Value="NHibernate.Driver.SqlClientDriver"/>
<add Key="connection.connection_string" Value="Data Source=.;Initial Catalog=NServiceBus;Integrated Security=SSPI"/>
<add Key="dialect" Value="NHibernate.Dialect.MsSql2008Dialect"/>
</NHibernateProperties>
</DBSubscriptionStorageConfig>
ERROR NHibernate.Tool.hbm2ddl.SchemaUpdate [(null)] <(null)> - could not get database metadata
System.Data.SqlClient.SqlException (0x80131904): Cannot open database "NServiceBus" requested by the login. The login failed.
Login failed for user 'SE1\fooservice'.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler,
SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK)
at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject,
TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity,
SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options,
Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection,
DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at NHibernate.Connection.DriverConnectionProvider.GetConnection()
at NHibernate.Tool.hbm2ddl.ManagedProviderConnectionHelper.Prepare()
at NHibernate.Tool.hbm2ddl.SchemaUpdate.Execute(Action`1 scriptAction, Boolean doUpdate)
错误NHibernate.Tool.hbm2ddl.SchemaUpdate[(null)]-无法获取数据库元数据
System.Data.SqlClient.SqlException(0x80131904):无法打开登录请求的数据库“NServiceBus”。登录失败。
用户“SE1\fooservice”登录失败。
位于System.Data.SqlClient.SqlInternalConnection.OneError(SqlException异常,布尔断开连接)
位于System.Data.SqlClient.TdsParser.throweexception和warning()处
在System.Data.SqlClient.TdsParser.Run(RunBehavior,SqlCommand cmdHandler,
SqlDataReader数据流,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)
位于System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(布尔值登记OK)
位于System.Data.SqlClient.SqlInternalConnectionDS.LoginOfAliver(ServerInfo服务器信息、字符串newPassword、Boolean redirectedUserInstance、SqlConnectionOwningObject、SqlConnectionString连接选项、超时超时)
在System.Data.SqlClient.SqlInternalConnectionDS.OpenLoginList(SqlConnection owningObject,
TimeoutTimer超时、SqlConnectionString连接选项、字符串newPassword、布尔重定向EduceInstance)
在System.Data.SqlClient.SqlInternalConnectionDS..ctor(DbConnectionPoolIdentity),
SqlConnectionString连接选项、对象提供信息、字符串newPassword、SqlConnection owningObject、Boolean redirectedUserInstance)
在System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions选项)中,
对象池组ProviderInfo、数据库连接池池、数据库连接所有者连接)
位于System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection所有者连接、DbConnectionPool池、DbConnectionOptions选项)
位于System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
位于System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
位于System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
位于System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection-owningConnection)
在System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection,
DbConnectionFactory(连接工厂)
在System.Data.SqlClient.SqlConnection.Open()处
在NHibernate.Connection.DriverConnectionProvider.GetConnection()处
在NHibernate.Tool.hbm2ddl.ManagedProviderConnectionHelper.Prepare()中
在NHibernate.Tool.hbm2ddl.SchemaUpdate.Execute(操作`1 scriptAction,布尔双更新)
使用自动(延迟启动)windows服务的启动类型是否可以解决此问题?我不认为这需要整整一分钟的延迟,这可能比在应用程序内部有一分钟的延迟更可取(特别是如果有一天数据库在另一台机器上,而sql server没有在那里运行。是否为自动(延迟启动)的windows服务使用启动类型修复它?我不认为它需要整整一分钟的延迟,这可能比在应用程序内部使用它更可取(特别是如果有一天数据库在另一台计算机上,而sql server没有在那里运行。我最终创建了一个类,该类实现了IWantCustomInitialization,以防止我的windows服务在连接到数据库之前启动。该类可能应该添加一些日志代码,但它解决了我的问题或者现在
这是密码
public class DbDependencyChecker : IWantCustomInitialization
{
private const int ConnectionRetries = 15;
private const int TimeBetweenRetries = 60000;
private const string DefaultConnectionName = "DbDependency";
private const string CustomConnectionNameKey = "DbDependencyConnectionName";
public void Init()
{
var connectionName = ConfigurationManager.AppSettings[CustomConnectionNameKey];
if (string.IsNullOrWhiteSpace(connectionName))
connectionName = DefaultConnectionName;
var providerName = ConfigurationManager.ConnectionStrings[connectionName].ProviderName;
var connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
if (string.IsNullOrWhiteSpace(providerName) || string.IsNullOrWhiteSpace(connectionString))
return;
for (var i = 0; i < ConnectionRetries; i++)
{
if (TryToConnect(providerName, connectionString))
break;
System.Threading.Thread.Sleep(TimeBetweenRetries);
}
}
private static bool TryToConnect(string providerName, string connectionString)
{
try
{
using (var connection = CreateConnection(providerName, connectionString))
{
connection.Open();
}
return true;
}
catch (Exception)
{
return false;
}
}
private static IDbConnection CreateConnection(string providerName, string connectionString)
{
var provider = DbProviderFactories.GetFactory(providerName);
var connection = provider.CreateConnection();
connection.ConnectionString = connectionString;
return connection;
}
}
公共类DbDependencyChecker:IWantCustomInitialization
{
私有常量int ConnectionRetries=15;
private const int TimeBetweenRetries=60000;
私有常量字符串DefaultConnectionName=“DbDependency”;
私有常量字符串CustomConnectionNameKey=“DbDependencyConnectionName”;
公共void Init()
{
var connectionName=ConfigurationManager.AppSettings[CustomConnectionNameKey];
if(string.IsNullOrWhiteSpace(connectionName))
connectionName=DefaultConnectionName;
var providerName=ConfigurationManager.ConnectionString[connectionName].providerName;
var connectionString=ConfigurationManager.connectionString[connectionName].connectionString;
if(string.IsNullOrWhiteSpace(providerName)| | string.IsNullOrWhiteSpace(connectionString))
返回;
对于(变量i=0;i<connectionStrings>
<add name="SomeDb" providerName="System.Data.SqlClient" connectionString="connection string" />
</connectionStrings>
<appSettings>
<add key="DbDependencyConnectionName" value="SomeDb"/>
</appSettings>
<connectionStrings>
<add name="DbDependency" providerName="System.Data.SqlClient" connectionString="connection string"/>
</connectionStrings>