65.9K
CodeProject 正在变化。 阅读更多。
Home

从C#进行Postgres数据库备份/恢复

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (7投票s)

2012 年 4 月 4 日

CPOL

3分钟阅读

viewsIcon

74584

downloadIcon

4897

Postgres数据库备份/恢复功能的实现。

引言

本文提供了Postgres数据库备份/恢复功能。使用此应用程序,我们可以检查系统中是否安装了Postgres数据库。如果安装了Postgres数据库,则会提供Postgres数据库列表。用户可以从列表中选择所需的数据库进行备份/恢复操作。

在我的项目中,我使用了Postgres作为数据库。这里我列出了一些**Postgres的优势**。

  • 更盈利的商业模式,具有大规模部署能力。
  • 任何阶段都不可能因许可证合规性而被审计。
  • 灵活地进行概念研究和试运行部署,无需额外许可证成本。

所需的DLL

从Visual Studio访问Postgres所需的DLL是Mono.Security.dllNpgsql.dll。我已经将这些DLL复制到应用程序的bin目录。建议仅将所需的DLL复制到bin目录。如果应用程序是Release配置,则可以删除Debug文件夹(Debug配置也适用)。

然后为应用程序添加这些引用

应用程序内部

检查Postgres安装

使用此应用程序,首先我们可以检查Postgres数据库是否已安装。单击“检查Postgres安装”按钮,它会检查系统服务列表中的Postgres服务。如果找到Postgres服务,则检查“pg_dump.exe”。如果找到该exe文件,则应用程序假定系统已安装Postgres,并且按钮背景颜色将变为绿色,数据库位置将显示在按钮旁边。

这是**检查Postgres服务**的代码。

bool bPostgresService = false;
ServiceController[] services = ServiceController.GetServices();
// try to find service name
foreach (ServiceController service in services)
{
    if (service.ServiceName.Contains("postgre") == true)
    {
        bPostgresService = true;
        break;
    }
              }
if (bPostgresService == true)
{
    PG_DumpExePath();
    objProcess.Kill();
    if (sbPG_dumpPath.Length != 0)
    {
        MessageBox.Show("Your System is INSATALLED with Postgres");
        labelLocation.Text = "Installation Location is " + strInstallLocation;
        labelLocation.Visible = true;
                 btnCheckPostgres.BackColor = Color.Green;
        panel1.Enabled = true;
    }
    
}
else
{
    objProcess.Kill();
    MessageBox.Show("Your System is NOT INSATALLED with Postgres");
}

以下是搜索文件的代码。对于此函数,提供文件名作为输入参数,该函数将在所有驱动器中搜索该文件,并返回该文件的位置。performFileSearchTask函数是一个**迭代文件搜索函数**。

private string LookForFile(string strFileName)
{
    string strPG_dumpPath = string.Empty;
    try
    {
        DriveInfo[] drives = DriveInfo.GetDrives();
        
        foreach (DriveInfo drive in drives)
        {
            strPG_dumpPath = performFileSearchTask(drive.Name, strFileName);
            if (strPG_dumpPath.Length != 0)
                break;
        }
        
    }
    catch (Exception ex)
      { }
    return strPG_dumpPath;
}

private string performFileSearchTask(string dirName, string strfileName)
{
    try
    {
        if (strPG_dumpPath.Length == 0)
        {
            try
            {

                foreach (string ddir in Directory.GetDirectories(dirName))
                {
                    System.Security.Permissions.FileIOPermission ReadPermission =
                        new System.Security.Permissions.FileIOPermission(
                        System.Security.Permissions.FileIOPermissionAccess.Write, ddir);
                    if (System.Security.SecurityManager.IsGranted(ReadPermission))
                    {
                        try
                        {
                            foreach (string dfile in Directory.GetFiles(ddir, strfileName))
                            {
                                strPG_dumpPath = ddir + "\\";
                                if (strPG_dumpPath.Length > 0)
                                {
                                    strInstallLocation = strPG_dumpPath;
                                    break;
                                }
                            }
                            if (strPG_dumpPath.Length == 0)
                                performFileSearchTask(ddir, strfileName);
                        }
                        catch (Exception ex)
                        { }
                    }
                    if (strPG_dumpPath != string.Empty)
                        break;
                }
            }
            catch (Exception ex)
            { }

        }
        
    }
    catch (Exception ex)
    { }
    return strPG_dumpPath;
}

如果系统安装了Postgres数据库,则应用程序仅提供备份/恢复选项。下一个操作需要单击“获取所有数据库”按钮。在此按钮旁边提供端口号文本框,用于输入所需的端口号以搜索数据库(在我的情况下为5432)。

try
{
    comboBox1.Items.Clear();
    comboBox1.Text = string.Empty;
    DataSet dsDB = new DataSet();
    strPort = txtPort.Text;
    strConnection = "Server=localhost;Port=" + strPort + 
      ";Database=postgres;Userid=postgres;Password=postgres;";

    dsDB = GetData("SELECT datname FROM pg_database WHERE " + 
      "datistemplate IS FALSE AND datallowconn IS TRUE AND datname!='postgres';");
    if (dsDB != null)
    {
        if (dsDB.Tables[0].Rows.Count > 0)
        {
            for (int i = 0; i < dsDB.Tables[0].Rows.Count; i++)
            {
                comboBox1.Items.Add(dsDB.Tables[0].Rows[i][0].ToString());
            }
            comboBox1.SelectedIndex = 0;
            strDatabaseName = comboBox1.Text;
            butSelectLoc.Enabled = true;
        }
        else
        {
            MessageBox.Show("No Database is existing");
            }
    }
}
catch (Exception ex)
{ }

此函数完成后,组合框将更新为可用的Postgres数据库。用户可以从组合框中选择要对其执行备份/恢复操作的数据库。

备份操作

首先,通过单击“选择备份文件保存位置”按钮选择要保存备份文件的位置。选择后,按钮下方的文本框将更新为备份文件的位置。备份文件格式为DbName_Backup_Date_HoursMin.Backup。

然后,用户可以单击“备份数据库”按钮。在此函数中,备份操作所需的脚本将被格式化为批处理文件,并作为进程执行。

private void butBackup_Click(object sender, EventArgs e)
{
    try
    {
        if (textBox1.Text == "-------")
        {
            MessageBox.Show("Select the location to save");
            return;
        }
        StreamWriter sw = new StreamWriter("DBBackup.bat");
        // Do not change lines / spaces b/w words.
        StringBuilder strSB = new StringBuilder(strPG_dumpPath);

        if (strSB.Length != 0)
        {
            strSB.Append("pg_dump.exe --host " + strServer + " --port " + strPort + 
              " --username postgres --format custom --blobs --verbose --file ");
            strSB.Append("\"" + textBox1.Text + "\"");
            strSB.Append(" \"" + strDatabaseName + "\r\n\r\n");
            sw.WriteLine(strSB);
            sw.Dispose();
            sw.Close();
            Process processDB = Process.Start("DBBackup.bat");
            do
            {//dont perform anything
            }
            while (!processDB.HasExited);
            {
                MessageBox.Show(strDatabaseName + " Successfully Backed up at " + textBox1.Text);
            }
        }
        else
        {
            MessageBox.Show("Please Provide the Location to take Backup!");
        }
    }
    catch (Exception ex)
    { }
}

这是形成strPG_dumpPath字符串所需的函数。此字符串对于备份和恢复函数都是通用的。我们提供了备份和恢复操作所需的pg_dump.exe的路径。

private void PG_DumpExePath()
{
    try
    {
        // Do not change lines / spaces b/w words.
        if (sbPG_dumpPath.Length == 0)
        {
            //string strPG_dumpPath = string.Empty;
            if (strPG_dumpPath == string.Empty)
            {
                strPG_dumpPath = LookForFile("pg_dump.exe");
                if (strPG_dumpPath == string.Empty)
                {
                    MessageBox.Show("Postgres is not installed");
                }
            }

            int a = strPG_dumpPath.IndexOf(":\\", 0);
            a = a + 2;
            string strSub = strPG_dumpPath.Substring(0, (a - 2));
            strPG_dumpPath = strPG_dumpPath.Substring(a, (strPG_dumpPath.Length - a));

            StringBuilder sbSB1 = new StringBuilder(strPG_dumpPath);
            sbSB1.Replace("\\", "\r\n\r\ncd ");

            StringBuilder sbSB2 = new StringBuilder("cd /D ");
            sbSB2.Append(strSub);
            sbSB2.Append(":\\");

            sbSB1 = sbSB2.Append(sbSB1);
            sbSB1 = sbSB1.Remove((sbSB1.Length - 3), 3);
            sbPG_dumpPath = sbSB1;
            strPG_dumpPath = sbSB1.ToString();
        }
    }
    catch (Exception ex)
    { }
}

备份操作完成后,将为所选位置创建输出备份文件。

恢复操作

首先,通过单击“选择备份文件路径”按钮选择要从中选择备份文件的位置。选择后,按钮下方的文本框将更新为备份文件名的位置。

然后,用户可以单击“恢复数据库”按钮。在此函数中,恢复操作所需的脚本将被格式化为批处理文件,并作为进程执行。

private void butRestore_Click(object sender, EventArgs e)
{
    try
    {
        if (txtBackupFilePath.Text == string.Empty)
        {
            MessageBox.Show("Select backup file");
            return;
        }
        //check for the pre-requisites before restoring the database.*********
        if (strDatabaseName != "")
        {
            if (txtBackupFilePath.Text != "")
            {
                StreamWriter sw = new StreamWriter("DBRestore.bat");
                // Do not change lines / spaces b/w words.
                StringBuilder strSB = new StringBuilder(strPG_dumpPath);
                if (strSB.Length != 0)
                {
                    checkDBExists(strDatabaseName);
                    strSB.Append("pg_restore.exe --host " + strServer + 
                       " --port " + strPort + " --username postgres --dbname");
                    strSB.Append(" \"" + strDatabaseName + "\"");
                    strSB.Append(" --verbose ");
                    strSB.Append("\"" + txtBackupFilePath.Text + "\"");
                    sw.WriteLine(strSB);
                    sw.Dispose();
                    sw.Close();
                    Process processDB = Process.Start("DBRestore.bat");
                    do
                    {//dont perform anything
                    }
                    while (!processDB.HasExited);
                    {
                        MessageBox.Show("Successfully restored " + 
                           strDatabaseName + " Database from " + txtBackupFilePath.Text);
                    }
                }
                else
                {
                    MessageBox.Show("Please enter the save path to get the backup!");
                }
            }
        }
        else
        {
            MessageBox.Show("Please enter the Database name to Restore!");
        }
    }
    catch (Exception ex)
    { }
}

结论

本文旨在演示如何获取Postgres数据库备份文件或从备份文件恢复数据库。

© . All rights reserved.