如何使基于NServiceBus主机的windows服务等待SQL Server启动?

如何使基于NServiceBus主机的windows服务等待SQL Server启动?,nservicebus,Nservicebus,我在与包含订阅存储数据库的SQL server实例相同的服务器上安装了多个NServiceBus通用基于主机的windows服务。当服务器启动时,my NServiceBus主机服务尝试在SQL server启动之前访问订阅存储数据库 以下是我迄今为止所尝试的: 在MSSQLSERVER上添加了windows服务器依赖项。这并没有解决问题 在IWantCustomInitialization.Init中添加了1分钟睡眠,以验证上述问题的原因。这解决了问题,但这是一个非常粗糙的解决方案 处理此问题

我在与包含订阅存储数据库的SQL server实例相同的服务器上安装了多个NServiceBus通用基于主机的windows服务。当服务器启动时,my NServiceBus主机服务尝试在SQL server启动之前访问订阅存储数据库

以下是我迄今为止所尝试的:

  • 在MSSQLSERVER上添加了windows服务器依赖项。这并没有解决问题
  • 在IWantCustomInitialization.Init中添加了1分钟睡眠,以验证上述问题的原因。这解决了问题,但这是一个非常粗糙的解决方案
  • 处理此问题的推荐方法是什么

    请在下面查找我的DBSubscriptionStorageConfig和当我的windows服务尝试启动时发生的异常,以供参考

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