TL;DR - 我希望服务器而不是我的应用程序进行备份,因为服务器已设置为这样做,而我的应用程序将无权访问。
背景
20 年前,我的公司为客户创建了用 Delphi 7/Pascal 编写的软件。我正在用 C# 重写软件。作为重写的一部分,我创建了新的 Firebird、Oracle 和 SQL Server 数据库。联邦法规要求维护所有现有数据,因此我创建了一个数据库修改/转换工具,以便从旧的数据库结构更改为新的数据库结构。
在开始进行更改之前,我需要备份现有数据库。运行此工具的技术人员无法访问其本地文件结构,也无法手动访问数据库所在的远程服务器。该工具访问本地系统上的一个类似加密.ini
的文件,以解析出连接字符串的组成部分并创建一个连接对象。然后,我使用该连接对象连接到技术人员计算机设置连接的同一数据库。这部分一切正常
如果我单独保留默认备份路径,它会尝试备份到默认路径但在本地计算机上(技术人员无权创建,我们也不希望技术人员访问 .bak)如果我修改默认备份路径是从连接字符串中获取的网络路径,我得到
SmoException:System.Data.SqlClient.SqlError:无法打开备份设备操作系统错误67(找不到网络名称。)。
因为文件路径不是网络共享(也不会是),并且数据库用户凭据无法从 SQL Server 外部访问该路径。
所以问题是:我如何将备份带到远程默认路径,就好像我在服务器上一样?
这是生成上述错误的代码(远程为空)。
public static void FullSqlBackup (Connection oldProactiveSql)
{
String sqlServerLogin = oldProactiveSql.UserName;
String password = oldProactiveSql.PassWord;
String instanceName = oldProactiveSql.InstanceName;
String remoteSvrName = oldProactiveSql.Ip + "," + oldProactiveSql.Port;
Server srv2;
Server srv3;
string device;
switch (oldProactiveSql.InstanceName)
{
case null:
ServerConnection srvConn2 = new ServerConnection(remoteSvrName);
srvConn2.LoginSecure = false;
srvConn2.Login = sqlServerLogin;
srvConn2.Password = password;
srv3 = new Server(srvConn2);
srv2 = null;
Console.WriteLine(srv3.Information.Version);
if (srv3.Settings.DefaultFile is null)
{
device = srv3.Information.RootDirectory + "\\DATA\\";
device = device.Substring(2);
device = oldProactiveSql.Ip + device;
}
else device = srv3.Settings.DefaultFile;
device = device.Substring(2);
device = string.Concat("\\\\", oldProactiveSql.Ip, device);
break;
default:
ServerConnection srvConn = new ServerConnection();
srvConn.ServerInstance = @".\" + instanceName;
srvConn.LoginSecure = false;
srvConn.Login = sqlServerLogin;
srvConn.Password = password;
srv2 = new Server(srvConn);
srv3 = null;
Console.WriteLine(srv2.Information.Version);
if (srv2.Settings.DefaultFile is null)
{
device = srv2.Information.RootDirectory + "\\DATA\\";
}
else device = srv2.Settings.DefaultFile;
break;
}
Backup bkpDbFull = new Backup();
bkpDbFull.Action = BackupActionType.Database;
bkpDbFull.Database = oldProactiveSql.DbName;
bkpDbFull.Devices.AddDevice(device, DeviceType.File);
bkpDbFull.BackupSetName = oldProactiveSql.DbName + " database Backup";
bkpDbFull.BackupSetDescription = oldProactiveSql.DbName + " database - Full Backup";
bkpDbFull.Initialize = true;
bkpDbFull.PercentComplete += CompletionStatusInPercent;
bkpDbFull.Complete += Backup_Completed;
switch (oldProactiveSql.InstanceName)
{
case null:
try
{
bkpDbFull.SqlBackup(srv3);
}
catch (Exception e)
{
Console.WriteLine (e);
Console.WriteLine(e.InnerException.Message);
throw;
}
break;
default:
try
{
bkpDbFull.SqlBackup(srv2);
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine(e.InnerException.Message);
throw;
}
break;
}
}
任何帮助将不胜感激,因为我现在只是在兜圈子。
从下面的评论中我会尝试 - 1. 在数据库上动态创建存储过程 [BackupToDefault] 然后运行它。2. 如果失败,则将数据库链接到自身。3. 尝试 - 在 [LinkedSelfSynonmym] 处执行 [BackupToDefault]
祝我好运,尽管它看起来很复杂,而且我希望它能奏效。