private void InitializeDatabaseAction(Action<InternalContext> action)
{
if (!_inDatabaseInitialization && !InitializerDisabled)
{
try
{
_inDatabaseInitialization = true;
// The idea here is that multiple threads can try to put an entry into InitializedDatabases
// at the same time but only one entry will actually make it into the collection, even though
// several may be constructed. The RetryAction ensures that that delegate only gets called
// exactly one time, thereby ensuring that database initialization will only happen once. But,
// sometimes the delegate will fail (and throw and exception). This may be due to some resource
// issue--most notably a problem with the database connection. In such a situation it makes
// sense to have initialization try again later when the resource issue has potentially been
// resolved. To enable this RetryAction will try again next time PerformAction called. We
// have to pass the context to PerformAction so that the next time it tries again it will use
// the new connection.
InitializedDatabases.GetOrAdd(
Tuple.Create(_model, _internalConnection.ConnectionKey),
t => new RetryAction<InternalContext>(action)).PerformAction(this);
}
finally
{
_inDatabaseInitialization = false;
_modelBeingInitialized = null;
}
}
}