从文本文件获取变量并处理多个数据库恢复

Getting variables from a text file and process mulitple database restores

我有一个 C# webform 应用程序需要从文本文件中读取数据库名称变量并处理恢复。我希望应用程序一个一个地恢复数据库,因为这个过程是敏感的。该文本文件最多可包含 10 个数据库以在一晚内恢复。单独读取数据库名称变量并为每个变量处理恢复的最佳方法是什么?我有大量的恢复代码,所以我想 运行 我的应用程序一次用于一个数据库,然后再次用于另一个数据库,然后再次用于另一个数据库,等等。我不需要我的代码 运行 很快,因为我有几个小时来完成恢复。

文本文件中的变量看起来像这样:

dbName:"dbName"
ServerToRestoreTo:"Server/instance"

dbName:"dbName2"
ServerToRestoreTo:"Server/instance2"

...
...
...
... up to 10 dbName and ServerToRestoreTo

此外,我仍在处理文本文件的结构,因此我愿意接受有关这部分的建议。

这是一种方法:维护一个单独的文件来跟踪您已经恢复的数据库。然后从主列表中选择第一个在 'RestoredDatabases.txt' 文件中没有条目的数据库。

更新

我创建了一个 class 来存储文本文件中的数据库信息,以及一个可以调用的方法,该方法将从您的文件结构中填充此 class 的列表。

首先,这里有一个 class 表示可以从文件读取或写入文件的数据库。 注意: 我覆盖了 ToString() 方法,因此它在您提到的相同文件结构中写入文本,并且我实现了 Equals 以允许在列表之间轻松比较对象。

private class LogFileDatabase
{
    public const string NamePrefix = "dbName:";
    public const string ServerPrefix = "ServerToRestoreTo:";

    public string DbName { get; set; }
    public string Server { get; set; }

    public override string ToString()
    {
        return string.Format("{0}\"{1}\"{2}{3}\"{4}\"",
            NamePrefix, DbName, Environment.NewLine, ServerPrefix, Server);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((LogFileDatabase) obj);
    }

    private bool Equals(LogFileDatabase other)
    {
        return (string.Equals(DbName, other.DbName) && 
            string.Equals(Server, other.Server));
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return ((DbName != null ? DbName.GetHashCode() : 0) * 397) ^
                    (Server != null ? Server.GetHashCode() : 0);
        }
    }
}

接下来,我编写了一个方法来读取一个文本文件,解析它以获取数据库和服务器名称,以及 return 上述 LogFileDatabase 个对象的列表:

private static IEnumerable<LogFileDatabase> GetDatabasesFromLog(string logPath)
{
    if (logPath == null) throw new ArgumentNullException("logPath");

    if (!File.Exists(logPath))
    {
        throw new FileNotFoundException(
            string.Format("logPath does not exist: {0}", logPath));
    }

    var databasesFromLog = new List<LogFileDatabase>();

    var fileLines = File.ReadAllLines(logPath)
        .Where(line => !string.IsNullOrWhiteSpace(line));

    var logFileDb = new LogFileDatabase();

    foreach (var fileLine in fileLines)
    {
        var dbNameIndex = fileLine.IndexOf(LogFileDatabase.NamePrefix);
        if (dbNameIndex > -1)
        {
            logFileDb.DbName = fileLine.Substring(
                dbNameIndex + LogFileDatabase.NamePrefix.Length).Replace("\"", "");

            continue;
        }

        var serverIndex = fileLine.IndexOf(LogFileDatabase.ServerPrefix);
        if (serverIndex == -1) continue;

        logFileDb.Server = fileLine.Substring(
            serverIndex + LogFileDatabase.ServerPrefix.Length).Replace("\"", "");

        databasesFromLog.Add(logFileDb);
        logFileDb = new LogFileDatabase();
    }

    return databasesFromLog;
}

最后,这里举例说明如何使用class和方法读取数据库文件,还原第一个不存在于还原的数据库文件中的数据库,然后写入名称还原的数据库到新文件:

public static void Main()
{
    // The file containing all databases to restore
    string databasesToRestore = "c:\program\settings\DatabasesToRestore.txt";

    // A file that will contain the names of databases that have already been restored
    string restoredDatabases = "c:\program\workingDir\RestoredDatabases.txt";

    if (File.Exists(databasesToRestore))
    {
        // Ensure restored databases file exists
        if (!File.Exists(restoredDatabases)) 
        { using (var tmp = File.Create(restoredDatabases)) { } }

        LogFileDatabase databaseToRestore =
            GetDatabasesFromLog(databasesToRestore)
                .Except(GetDatabasesFromLog(restoredDatabases))
                .FirstOrDefault();

        if (databaseToRestore != null)
        {
            // Call retore database code here, restoring `databaseToRestore`
            RestoreDbToServer(databaseToRestore.DbName, databaseToRestore.Server);

            // Write the name of the database we just restored 
            // to our 'restoredDatabases` file       
            File.AppendAllLines(restoredDatabases,
                new List<string> {databaseToRestore.ToString()});
        }
        else
        {
            // There are no databases left to restore, 
            // so we can delete our `restoredDatabases` file now.
            // But be careful - this means when you run the program again, 
            // it will start restoring the first database.
            File.Delete(restoredDatabases);
        }
    }
}