C# Winform 實作Oracle 資料庫備份軟體
Oracle資料庫備份軟體,實作定時自動備份,并且可以将備份檔案以郵件附件的形式發送到指定郵箱。
正常手動備份資料庫的時候,大多時候是使用指令行進行備份。
導出資料庫的指令是:
exp 使用者名/密碼@資料庫執行個體名 file=本地存放路徑 log=本地日志存放路徑
導入資料庫的指令是:
imp 使用者名/密碼@資料庫執行個體名 file=本地資料庫檔案 fromuser=原使用者名 touser=目前使用者名 log=本地日志存放路徑
是以實作自動備份資料庫的思路就是定時執行一條導出資料庫的cmd指令。
一、軟體設計
1、主窗體:分上下兩部分,上邊是資料庫備份配置清單,下邊是備份記錄清單。

2、設定:設定備份完成後是否發送郵件進行通知,設定是否發送資料庫備份到郵箱,設定日志的存放路徑。
3、建立備份:配置帶備份的資料庫資訊
4、建立導出:點選确定直接導出資料庫到本地,隻是單次導出
5、建立導入:點選确定導入資料庫,隻是單次導入
二、代碼實作
1、本程式中的資料庫備份配置和設定頁面的内容都是儲存到json檔案中,是以需要對json檔案進行操作:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace BackUp.Winform.Class
{
public static class Json
{
/// <summary>
/// 儲存設定
/// </summary>
/// <param name="model"></param>
public static void SaveSetting(Models.Setting model)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(model);
SaveJson("Setting", json);
}
/// <summary>
/// 儲存記錄
/// </summary>
/// <param name="model"></param>
public static void SaveRecord(Models.Record model)
{
var lstModel = GetRecord();
lstModel.Add(model);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(lstModel);
SaveJson("Record", json);
}
/// <summary>
/// 删除記錄
/// </summary>
/// <param name="database"></param>
/// <param name="username"></param>
/// <param name="starttime"></param>
/// <param name="endtime"></param>
public static void DelRecord(string database, string username, DateTime starttime, DateTime endtime)
{
var lstModel = GetRecord();
int index = lstModel.FindIndex(x => x.DataBase == database && x.Username == username && x.StartTime.ToString("yyyyMMddHHmmss") == starttime.ToString("yyyyMMddHHmmss") && x.EndTime.ToString("yyyyMMddHHmmss") == endtime.ToString("yyyyMMddHHmmss"));
if (index > -1)
{
lstModel.RemoveAt(index);
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(lstModel);
SaveJson("Record", json);
}
/// <summary>
/// 儲存備份配置
/// </summary>
/// <param name="model"></param>
public static void SaveBackUp(Models.BackUp model)
{
var lstModel = GetBackUp();
lstModel.Add(model);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(lstModel);
SaveJson("BackUp", json);
}
/// <summary>
/// 修改備份配置
/// </summary>
/// <param name="model"></param>
public static void EditBackUp(Models.BackUp model)
{
var lstModel = GetBackUp();
int index = lstModel.FindIndex(x => x.UuId == model.UuId);
lstModel.RemoveAt(index);
lstModel.Add(model);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(lstModel);
SaveJson("BackUp", json);
}
/// <summary>
/// 删除備份配置
/// </summary>
/// <param name="uuId"></param>
public static void DelBackUp(string uuId)
{
var lstModel = GetBackUp();
int index = lstModel.FindIndex(x => x.UuId == uuId);
if (index > -1)
{
lstModel.RemoveAt(index);
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(lstModel);
SaveJson("BackUp", json);
}
/// <summary>
/// 擷取設定
/// </summary>
/// <returns></returns>
public static Models.Setting GetSetting()
{
string json = GetJson("Setting");
return string.IsNullOrEmpty(json)
? new Models.Setting() : Newtonsoft.Json.JsonConvert.DeserializeObject<Models.Setting>(json);
}
/// <summary>
/// 擷取記錄
/// </summary>
/// <returns></returns>
public static List<Models.Record> GetRecord()
{
string json = GetJson("Record");
return string.IsNullOrEmpty(json)
? new List<Models.Record>() : Newtonsoft.Json.JsonConvert.DeserializeObject<List<Models.Record>>(json).OrderByDescending(p=>p.EndTime).ToList();
}
/// <summary>
/// 擷取備份配置
/// </summary>
/// <returns></returns>
public static List<Models.BackUp> GetBackUp()
{
string json = GetJson("BackUp");
return string.IsNullOrEmpty(json)
? new List<Models.BackUp>() : Newtonsoft.Json.JsonConvert.DeserializeObject<List<Models.BackUp>>(json).OrderByDescending(p => p.PostTime).ToList();
}
/// <summary>
/// 儲存JSON資料
/// </summary>
/// <param name="filename"></param>
/// <param name="json"></param>
private static void SaveJson(string filename, string json)
{
try
{
string exeFolder = System.Windows.Forms.Application.StartupPath + "\\";
string Directory = exeFolder + "Json\\";
string filepath = Directory + "\\" + filename + ".json";
if (!System.IO.Directory.Exists(Directory))
System.IO.Directory.CreateDirectory(Directory);
File.WriteAllText(filepath, json);
}
catch (Exception e)
{
WriteTxt("儲存JSON", $"{filename}.json 儲存出錯:\r\n{e.Message}");
}
}
/// <summary>
/// 擷取JSON資料
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
private static string GetJson(string filename)
{
string res = "";
try
{
string exeFolder = System.Windows.Forms.Application.StartupPath + "\\";
string Directory = exeFolder + "Json\\";
string filepath = Directory + "\\" + filename + ".json";
// 建立一個 StreamReader 的執行個體來讀取檔案
// using 語句也能關閉 StreamReader
using (StreamReader sr = new StreamReader(filepath))
{
string line;
// 從檔案讀取并顯示行,直到檔案的末尾
while ((line = sr.ReadLine()) != null)
{
res += line;
}
}
}
catch (Exception e)
{
WriteTxt("擷取JSON", $"{filename}.json 讀取出錯:\r\n{e.Message}");
}
return res;
}
/// <summary>
/// 記錄日志
/// </summary>
/// <param name="folder">該日志所在檔案夾名字</param>
public static void WriteTxt(string folder, string content)
{
try
{
string exeFolder = System.Windows.Forms.Application.StartupPath + "\\";
string Directory = exeFolder + "logs\\" + folder;
string filepath = Directory + "\\日志(" + DateTime.Now.ToString("yyyy-MM-dd") + ").txt";
if (!System.IO.Directory.Exists(Directory))
System.IO.Directory.CreateDirectory(Directory);
StreamWriter sw = new StreamWriter(filepath, true, Encoding.UTF8);
sw.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]:");
sw.WriteLine("***************************分隔符【開始】***********************************");
sw.WriteLine(content);
sw.WriteLine("***************************分隔符【結束】***********************************\r\n");
sw.Close();
}
catch { }
}
}
}
2、實作自動備份和導出導入的思路是執行cmd指令,是以需要對cmd指令進行操作:
/// <summary>
/// 執行cmd指令
/// </summary>
public void RunCmd()
{
lock (_cmd)
{
try
{
//string strInput = Console.ReadLine();
Process p = new Process();
//設定要啟動的應用程式
p.StartInfo.FileName = "cmd.exe";
//是否使用作業系統shell啟動
p.StartInfo.UseShellExecute = false;
// 接受來自調用程式的輸入資訊
p.StartInfo.RedirectStandardInput = true;
//輸出資訊
p.StartInfo.RedirectStandardOutput = true;
// 輸出錯誤
p.StartInfo.RedirectStandardError = true;
//不顯示程式視窗
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);
//啟用Exited事件
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(Process_Exited);
//啟動程式
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.StandardInput.AutoFlush = true;
//輸入指令
_startTime = DateTime.Now;
p.StandardInput.WriteLine(_cmd);
p.StandardInput.WriteLine("exit");
}
catch (Exception ex)
{
Class.Json.WriteTxt("CMD", $"執行cmd指令出錯:\r\ncmd:{_cmd}\r\n{ex.Message}");
}
}
}
private void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
SetLogContent(e.Data);
}
}
private void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
SetLogContent(e.Data);
}
}
private void Process_Exited(object sender, EventArgs e)
{
//備份的時候要更新配置中的下次執行時間
if (_backUp.Type == Models.BackType.備份)
{
_backUp.LastExecuteTime = _startTime;
_backUp.NextExecuteTime = GetNextExecuteTime(_startTime, _backUp.Times);
Class.Json.EditBackUp(_backUp);
}
SetLogContent("指令執行完畢");
WriteTxt(_logFolder);
_isok = _logsContent.Contains("成功")&& !_logsContent.Contains("未成功");
_isloading = false;
_endTime = DateTime.Now;
SaveRecord();
}
3、導入和導出隻需要将填寫到textbox中的内容拼接成一句導出或導入的cmd指令,然後扔到這個方法裡執行就可以了。重點是如何自動備份資料庫,也就是如何定時自動執行一條導出的cmd指令。
其實隻需要用到timer控件。
在主窗體中拖入timer控件
設定四秒鐘執行一次
然後在主窗體的構造函數中啟動該timer
public Fm_Main()
{
InitializeComponent();
fm_Loading = new Fm_Loading();
timer.Start();
timerBackUp.Start();//啟動備份定時器
}
寫一個自動備份的方法,供timerBackUp調用
/// <summary>
/// 自動備份
/// </summary>
private void BackUpAuto()
{
lock (BackUp.Username)
{
if (IsExceing) return;
if (BackUp == null) return;
string now = DateTime.Now.ToString("yyyyMMddHHms");
string cmd = $"exp {BackUp.Username}/{BackUp.Password}@{BackUp.DataBase} file={BackUp.Path}\\Backup_{BackUp.Username}_{now}.dmp";
if (BackUp.IsLogs)
{
cmd += $" log={BackUp.LogPath}\\Backup_{BackUp.Username}_{now}.log";
}
ThreadRun(cmd, $"{BackUp.Path}\\Backup_{BackUp.Username}_{now}.dmp", BackUp, "自動備份");
}
}
這裡啟動另一個線程去執行cmd指令
/// <summary>
/// 線程裡運作
/// </summary>
/// <param name="cmd"></param>
/// <param name="filePath"></param>
/// <param name="backUp"></param>
/// <param name="logsfolder"></param>
private void ThreadRun(string cmd, string filePath, Models.BackUp backUp, string logsfolder)
{
FilePath = filePath;
Cmd = cmd;
LogsFolder = logsfolder;
BackUp = backUp;
bool isSuccess = false;
fm_Loading = new Fm_Loading();
IsExceing = true;
tsslStatus.Text = $@"狀态:正在{logsfolder}...";
tsslStatus.ForeColor = Color.Black;
fm_Loading = new Fm_Loading();
Thread th = new Thread(new ThreadStart(RunCmd));//這裡調用的就是前邊定義的執行cmd指令的方法
th.Start();
IsExceing = false;
isSuccess = fm_Loading.ShowDialog() == DialogResult.OK;
tsslStatus.Text = isSuccess ? $@"狀态:{logsfolder}成功" : $@"狀态:{logsfolder}失敗";
tsslStatus.ForeColor = isSuccess ? Color.Green : Color.Red;
if (isSuccess && BackUp.Type != Models.BackType.導入)
{
SendMail($"Oracle資料庫{logsfolder}:{BackUp.Username}",
Newtonsoft.Json.JsonConvert.SerializeObject(BackUp), FilePath);
}
}
在timer的tick事件中寫如下代碼,實作定時備份:
private void timerBackUp_Tick(object sender, EventArgs e)
{
DateTime thisTime = DateTime.Now;
//判斷備份配置清單中下一次執行時間是否在目前時間的前兩秒和後兩秒内
var backUp = BackUps.Find(x =>
x.NextExecuteTime < thisTime.AddSeconds(2) && x.NextExecuteTime > thisTime.AddSeconds(-2));
if (backUp != null && backUp.IsUse)
{
if (IsExceing) return;
BackUp = backUp;
BackUpAuto();
LoadBackUpList();
}
}
以上就是實作一個自動備份Oracle資料庫程式的思路了,具體的代碼我放到了以下兩個地方:
CSDN:有現成的軟體和源碼,下載下傳需要積分:
軟體:https://download.csdn.net/download/weixin_42281203/13204541
源碼:https://download.csdn.net/download/weixin_42281203/13204560
Gitee:隻有源碼,下載下傳位址:https://gitee.com/blackvon/oracle-back-up
歡迎通路作者個人技術部落格:BlackvonCode(www.blackvon.top)
作者的微信公衆号和小程式
![]()
C# Winform 實作Oracle 資料庫備份軟體C# Winform 實作Oracle 資料庫備份軟體