public void CheckSchema(SQLiteConnection connection)
{
long version = GetSchemaVersion(connection);
if (version == SchemaVersion) // database uses current schema version bail
{
return;
}
if (version > SchemaVersion)
{
throw new InvalidOperationException(
String.Format("Unsupported schema version. Database uses newer schema ({0}) than application ({1}).", version, SchemaVersion));
}
lock (_syncRoot)
{
// reload the schema version to make sure that the database schema was not already updated
version = GetSchemaVersion(connection);
// database has not yet been initialized
if (version == 0)
{
InitDatabase(connection);
// since we have created new database we don't need to execute any migration logic
return;
}
string backupName = String.Format("backup-v{0}-{1}.sqlite", version, DateTime.Now.ToString("yyyyMMdd-HHmmssFF"));
if (!BackupDatabase(connection, backupName))
{
_log.Warn("Unable to perform backup. Will continue with upgrade.");
}
IDictionary<long, ISchemaMigrator> migrators =
ReflectionHelper.GetInstances<ISchemaMigrator>(this.GetType().Assembly, Enumerable.Empty<Type>())
.ToDictionary(sm => sm.FromVersion);
int loopCount = 0; // this will ensure that we will not end up looping forever
do
{
ISchemaMigrator migrator;
migrators.TryGetValue(version, out migrator);
if (migrator != null)
{
migrator.Migrate(connection);
}
else
{
System.Diagnostics.Debug.Assert(false, "Migrator for this version of schema not found.");
_log.WarnFormat("Migrator from database schema version {0} was not found.", version);
}
version = GetSchemaVersion(connection);
} while (version < SchemaVersion && ++loopCount < SchemaVersion);
}
}