最近查了一下网上远程备份数据库的方法,好像还是个挺麻烦的事情。但是项目里必须加入这个模块,所以也只有死磕出一个了。最后总结出2个方案:
第一种方案,是我个人比较喜欢的方案:
首先用SqlDataAdapter将所有表加载到DataSet中,用DataSet类的写入XML方法,将所有的信息全部写入到XML中。
需要还原的时候,首先用SqlDataAdapter去查询加载数据库的内容,然后再读取DataSet,最后用SqlDataAdapter的update()就行了。
具体代码就不写了,这种方法很简单,用起来也方便。
第二种方案,是真正的备份数据库文件。
我们都知道,直接远程备份数据库并没有什么问题,但是备份文件只能在服务器上,通过什么传送到客户端是个难点。但是数据库有个功能是cmdshell,可以通过它向数据库所在的服务器发送DOS命令,直接操作服务器。呵呵,是不是很有黑客的味道?但是这种做法并不难,可以完全通过SQL语句来完成。
1.首先需要开启数据库的cmdshell功能:
EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
好了,现在我们已经完全控制了服务器。如果服务器的登录用户名不允许操作服务器,你可以新建用户,提升权限
exec xp_cmdshell 'net user mm 123 /add' --添加一用户
exec xp_cmdshell 'net localgroup administrators mm /add' --为用户添加管理员权限
2.在客户端建立一个共享文件夹。
3.服务器建立到共享文件夹的映射。
exec master..xp_cmdshell 'net use z: //客户端IP/共享文件夹的共享名 "客户端的WINDOWS登录密码" /user:服务器IP/客户端的WINDOWS用户名'
Z,就是映射名。如果不知道什么是映射,可以自己试着建一个。右键我的电脑,映射网络驱动器。随便映射到某个共享文件夹。这样在我的电脑里面,就会多一个"Z盘",进去后直接就是这个共享文件夹了。需要注意的是,这里涉及到一些网络方面的知识,比如你和服务器不在同一个域,建映射可能就会出问题。而数据库给你的提示总是很奇怪的,比如什么错误的用户名。
4.备份服务器上的数据库 with init覆盖 ¦ noinit添加
backup database 库名 to disk='C:/备份文件名.bak' with init
5.将备份文件拷贝到映射盘
exec master..xp_cmdshell 'copy C:/备份文件名.bak z:'
6.清除痕迹(黑客来过了,当然要清理痕迹啦)
--exec master..xp_cmdshell 'del C:/备份文件名.bak' 删除备份文件
--exec master..xp_cmdshell 'net use z: /delete' 删除映射
注意点:
需要注意的是,如果建立映射失败,或者删除映射失败,数据库只是返回一个失败原因,对于程序来说依然算“得到查询结果”,而不是返回异常。所以在用C#写代码的时候,不要用catch去捕获失败的操作。而是因为根据返回结果的值来判断。
再附上设置本地文件夹为共享的代码:
/// <summary>
/// 设置文件夹共享
/// </summary>
/// <param name="FolderPath">文件夹路径</param>
/// <param name="ShareName">共享名</param>
/// <param name="Description">共享注释</param>
/// <returns></returns>
public int ShareNetFolder(string FolderPath, string ShareName, string Description)
{
try
{
ManagementClass managementClass = new ManagementClass("Win32_Share");
// Create ManagementBaseObjects for in and out parameters
ManagementBaseObject inParams = ("Create");
ManagementBaseObject outParams;
// Set the input parameters
inParams["Description"] = Description;
inParams["Name"] = ShareName;
inParams["Path"] = FolderPath;
inParams["Type"] = 0x0; // Disk Drive
//Another Type:
// DISK_DRIVE = 0x0
// PRINT_QUEUE = 0x1
// DEVICE = 0x2
// IPC = 0x3
// DISK_DRIVE_ADMIN = 0x80000000
// PRINT_QUEUE_ADMIN = 0x80000001
// DEVICE_ADMIN = 0x80000002
// IPC_ADMIN = 0x8000003
//inParams["MaximumAllowed"] = int maxConnectionsNum;
// Invoke the method on the ManagementClass object
outParams = ("Create", inParams, null);
// Check to see if the method invocation was successful
if ((uint)(["ReturnValue"].Value) != 0)
{
throw new Exception("Unable to share directory.");
}
}
catch
{
return -1;
}
return 0;
}
/// <summary>
/// 取消文件夹共享
/// </summary>
/// <param name="ShareName">文件夹的共享名</param>
/// <returns></returns>
public int CancelShareNetFolder(string ShareName)
{
try
{
SelectQuery selectQuery = new SelectQuery("Select * from Win32_Share Where Name = '" + ShareName + "'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery);
foreach (ManagementObject mo in ())
{
("Delete", null, null);
}
}
catch
{
return -1;
}
return 0;
}