tbf/Results/Entities/helpers/DatabaseMigrationHelper.cs

159 lines
5.9 KiB
C#
Raw Normal View History

using System;
using Common;
using log4net;
using MySql.Data.MySqlClient;
namespace Results.Entities.helpers
{
/// <summary>
/// Applies explicit, backwards-compatible results DB migrations before the
/// first NHibernate session factory is created.
/// </summary>
public static class DatabaseMigrationHelper
{
private static readonly ILog log = LogManager.GetLogger(typeof(DatabaseMigrationHelper));
public static void EnsureSchema(DBType dbType, string connectionString)
{
switch (dbType)
{
case DBType.MySql:
EnsureMySqlSchema(connectionString);
break;
case DBType.SQLite:
EnsureSQLiteSchema(connectionString);
break;
}
}
private static void EnsureMySqlSchema(string connectionString)
{
using (var conn = new MySqlConnection(connectionString))
{
conn.Open();
// Added by newer MeterTestRslt mapping; older customer DBs do
// not contain it and otherwise reject the entire batch insert.
EnsureColumnMySql(conn, "MeterTestRslt", "PulsesPerKilogram", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestRslt", "FlipMode", "INT NULL");
EnsureColumnMySql(conn, "MeterTestRslt", "ExtraDataPath", "VARCHAR(255) NULL");
EnsureMeterTestResultExtraColumnsMySql(conn);
}
}
private static void EnsureMeterTestResultExtraColumnsMySql(MySqlConnection conn)
{
for (int index = 1; index <= 9; index++)
{
EnsureColumnMySql(conn, "MeterTestRslt", "X" + index, "FLOAT NOT NULL DEFAULT 0");
}
}
private static void EnsureColumnMySql(
MySqlConnection conn,
string tableName,
string columnName,
string columnDefinition)
{
using (var transaction = conn.BeginTransaction())
{
try
{
bool exists;
using (var cmd = conn.CreateCommand())
{
cmd.Transaction = transaction;
cmd.CommandText = @"
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = @tableName
AND COLUMN_NAME = @columnName";
cmd.Parameters.AddWithValue("@tableName", tableName);
cmd.Parameters.AddWithValue("@columnName", columnName);
exists = Convert.ToInt32(cmd.ExecuteScalar()) > 0;
}
if (!exists)
{
using (var alter = conn.CreateCommand())
{
alter.Transaction = transaction;
alter.CommandText = "ALTER TABLE `" + tableName + "` ADD COLUMN `" +
columnName + "` " + columnDefinition;
alter.ExecuteNonQuery();
log.WarnFormat("Results DB migration: added {0}.{1} ({2}).",
tableName, columnName, columnDefinition);
}
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
private static void EnsureSQLiteSchema(string databaseFile)
{
using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=" + databaseFile))
{
conn.Open();
EnsureColumnSQLite(conn, "MeterTestRslt", "PulsesPerKilogram", "REAL NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestRslt", "FlipMode", "INTEGER NULL");
EnsureColumnSQLite(conn, "MeterTestRslt", "ExtraDataPath", "TEXT NULL");
EnsureMeterTestResultExtraColumnsSQLite(conn);
}
}
private static void EnsureMeterTestResultExtraColumnsSQLite(System.Data.SQLite.SQLiteConnection conn)
{
for (int index = 1; index <= 9; index++)
{
EnsureColumnSQLite(conn, "MeterTestRslt", "X" + index, "REAL NOT NULL DEFAULT 0");
}
}
private static void EnsureColumnSQLite(
System.Data.SQLite.SQLiteConnection conn,
string tableName,
string columnName,
string columnDefinition)
{
bool exists = false;
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "PRAGMA table_info(" + tableName + ")";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if (string.Equals(reader["name"].ToString(), columnName,
StringComparison.OrdinalIgnoreCase))
{
exists = true;
break;
}
}
}
}
if (!exists)
{
using (var alter = conn.CreateCommand())
{
alter.CommandText = "ALTER TABLE " + tableName + " ADD COLUMN " +
columnName + " " + columnDefinition;
alter.ExecuteNonQuery();
log.WarnFormat("Results DB migration: added {0}.{1} ({2}).",
tableName, columnName, columnDefinition);
}
}
}
}
}