我正在使用Windows服务,该服务将在特定文件夹中查找备份文件。找到新的备份文件后,该服务将从该位置移走所有备份文件,并将它们移至存档文件夹,然后还原数据库并在其中触发存储过程。
我以前使用过FileSystemWatcher
,但是由于它在服务器上不起作用,所以我使用DirectoryInfo
查找文件。
using System.Collections.Generic;
using System.Data;
using System.ServiceProcess;
using System.IO;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using System.Data.SqlClient;
using System.Configuration;
using System.Net.Configuration;
using System;
using System.Linq;
using System.Net.Mail;
using System.Timers;
using System.Threading;
namespace DashboardDataRefresh
{
public partial class Service : ServiceBase
{
/// <summary>
/// Component initializer.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
public Service()
{
InitializeComponent();
}
/// <summary>
/// Component initializer. What Happens when the Service starts.
/// </summary>
protected override void OnStart(string[] args)
{
DirectoryInfo dir = new DirectoryInfo(backupdirectory);
try
{
// Determine whether the dirrectory exists.
if (!dir.Exists)
{
// Indicate that the dirrectory already exists.
}
// Move all the Backup files to Processed folder at certain intervals.
createOrderTimer = new System.Timers.Timer();
createOrderTimer.Elapsed += CreateOrderTimer_Elapsed;
createOrderTimer.Interval = TimeSpan.FromMinutes(5).TotalMilliseconds; // 5 min
MoveToProcessed(processed);
createOrderTimer.Enabled = true;
createOrderTimer.AutoReset = true;
}
catch (Exception e)
{
// Catch Ex
}
}
/// <summary>
/// Elapsed event handler calls our other method
/// </summary>
private void CreateOrderTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MoveToProcessed(processed);
}
/// <summary>
/// Copy all the backup files to Processed folder.
/// </summary>
private void MoveToProcessed(string processed)
{
string pattern = "*.bak";
DirectoryInfo dirTarget = new DirectoryInfo(processed);
DirectoryInfo dirSource = new DirectoryInfo(backupdirectory);
try {
foreach (FileInfo file in dirSource.GetFiles(pattern))
{
file.MoveTo(Path.Combine(dirTarget.ToString(), file.Name));
}
var Latestfile = (from f in dirTarget.GetFiles(pattern) orderby f.LastWriteTime descending select f).First();
// Restore Begins.
RestoreDatabase(Latestfile.FullName);
}
catch(Exception e)
{
// Catch Ex.
}
}
/// <summary>
/// Restore Database.
/// </summary>
private void RestoreDatabase(string latestFile)
{
string db_name = ConfigurationManager.AppSettings["database"];
string server_name = ConfigurationManager.AppSettings["serverName"];
string user_name = ConfigurationManager.AppSettings["userName"];
string password = ConfigurationManager.AppSettings["password"];
String _sp_connectionString = "Server=" + ConfigurationManager.AppSettings["sp_serverName"] +
";DataBase=" + ConfigurationManager.AppSettings["sp_database"] +
";User Id=" + ConfigurationManager.AppSettings["sp_userName"] +
";Password=" + ConfigurationManager.AppSettings["sp_password"];
try
{
Restore sqlRestore = new Restore();
BackupDeviceItem deviceItem = new BackupDeviceItem(latestFile, DeviceType.File);
sqlRestore.Devices.Add(deviceItem);
sqlRestore.Database = db_name;
ServerConnection connection = new ServerConnection(server_name, user_name, password);
Server sqlServer = new Server(connection);
Database db = sqlServer.Databases[db_name];
sqlRestore.Action = RestoreActionType.Database;
db = sqlServer.Databases[db_name];
sqlRestore.ReplaceDatabase = true;
// Restoration in process. The Database is Restored at a Default location. Under the DATA Folder.
sqlRestore.SqlRestore(sqlServer);
db = sqlServer.Databases[db_name];
db.SetOnline();
sqlServer.Refresh();
// Calling SP.
InvokeSP(_sp_connectionString);
}
catch (Exception e)
{
// Catch Ex.
}
}
/// <summary>
/// Invokes SP from other Database after restore is complete.
/// </summary>
private void InvokeSP(string connStr)
{
SqlConnection conn = new SqlConnection(connStr);
try
{
conn.Open();
//1. Create a command object identifying the stored procedure.
SqlCommand cmd = new SqlCommand(ConfigurationManager.AppSettings["storedProdcedure"], conn);
cmd.CommandTimeout = 0;
// 2. set the command object so it knows to execute a stored procedure.
cmd.CommandType = CommandType.StoredProcedure;
// Add a check here as well.
// execute the command.
SqlDataReader rdr = cmd.ExecuteReader();
// Since we are not using - using block we have to explicitly call Close() to close the connection.
conn.Close();
}
catch (SqlException SqlEx)
{
// Catch Ex.
}
finally
{
conn.Close();
}
}
}
}