我在与包含我的订阅存储数据库的SQL Server实例相同的服务器上安装了几个基于NServiceBus通用主机的Windows服务。当服务器引导我的NServiceBus主机服务时,尝试在SQL Server启动之前访问订阅存储数据库。
这是我到目前为止所尝试的内容:
处理此问题的推荐方法是什么?
供参考查找我的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)
答案 0 :(得分:1)
我最终创建了一个实现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;
}
}
配置文件如下所示:
<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>
答案 1 :(得分:0)
使用启动类型为自动(延迟启动)的Windows服务修复它吗?不会认为它需要一分钟的延迟,这可能比应用程序的内部更令人满意(特别是如果你有一天在另一台机器上有数据库并且没有在那里运行sql server。