我正在构建一个C#控制台应用程序,该应用程序使用预定义参数恢复SQL Server数据库,该参数可以在交换机菜单中进行修改。这个应用程序的重点是简单。它是为任何人设计的,只要按下一个按钮即可恢复SQL Server数据库。是的,应该有人可以胜任这项工作,但是有很多方法可以完成工作......无论如何,我已经建立了逻辑来循环备份目录,并根据点选择正确的备份文件及时。除了实际恢复部分之外,一切都可以工C# - 使用内联SQL恢复SQL Server数据库
从我读过的其他问题来看,我担心从C#运行SQL来修改服务器是不可能的。我不愿意使用SMO对象,因为这涉及到我想要避免的额外复杂性,但是如果这是我能做到的唯一方法,那么这就是我要做的。
每当我尝试运行此代码时,它会抱怨@dbName
值无效。
public static void RestoreDatabase(string Server_Name, string Instance_Name, string DB_Name, FileInfo BakFile, FileInfo DiffFile, FileInfo TrnFile, DateTime Point_In_Time)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=" + Server_Name + "\\" + Instance_Name + ";Initial Catalog=master;Integrated Security=True";
string SqlQuery = @"ALTER DATABASE @dbName
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE @dbName
FROM DISK = @BakFilePath
WITH NORECOVERY, REPLACE;
RESTORE DATABASE @dbName
FROM DISK = @DiffFilePath
WITH NORECOVERY;
RESTORE DATABASE @dbName
FROM DISK = @TrnFilePath
WITH RECOVERY, STOPAT = @RecoveryTime;
ALTER DATABASE @dbName
SET MULTI_USER;";
SqlCommand cmd = new SqlCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = SqlQuery;
try
{
cmd.Parameters.Add(new SqlParameter("@dbName", SqlDbType.NVarChar, 30));
cmd.Parameters.Add(new SqlParameter("@BakFilePath", SqlDbType.NVarChar, 255));
cmd.Parameters.Add(new SqlParameter("@DiffFilePath", SqlDbType.NVarChar, 255));
cmd.Parameters.Add(new SqlParameter("@TrnFilePath", SqlDbType.NVarChar, 255));
cmd.Parameters.Add(new SqlParameter("@RecoveryTime", SqlDbType.DateTime));
cmd.Parameters["@dbName"].Value = DB_Name;
cmd.Parameters["@BakFilePath"].Value = BakFile.FullName;
cmd.Parameters["@DiffFilePath"].Value = DiffFile.FullName;
cmd.Parameters["@TrnFilePath"].Value = TrnFile.FullName;
cmd.Parameters["@RecoveryTime"].Value = Point_In_Time;
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
}
try
{
Console.WriteLine("Restoring {0}...", DB_Name);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Connection.Close();
Console.WriteLine("Restore Complete!");
Console.ReadLine();
}
catch (SqlException ex)
{
Console.WriteLine("Connection could not open. Error: {0}", ex);
Console.ReadLine();
}
}
2016年8月15日10:38
基于一些问题的答案,你们都建议动态SQL。我很担心SQL注入,但只有管理员才能访问这个程序。无论如何,我仍然会加入更严格的验证,因为谁不喜欢把垃圾输入放入踢球。
我曾尝试动态SQL。这是我的代码,但我没有花太多时间检查错误,所以我会再次走这条路线,并尝试清理任何错误。
string SqlQuery = string.Format(@"DECLARE @dbName NVARCHAR(MAX), @strSQL NVarchar(MAX)=N'';
SET @dbName = {0};
SELECT
@strSQL += 'DECLARE @BakFilePath nvarchar(255) = N''{1}'','
+ N' @DiffFilePath nvarchar(255) = N''{2}'','
+ N' @TrnFilePath nvarchar(255) = N''{3}'','
+ N' @RecoveryTime DateTime = N''{4}'''
+ N' ALTER DATABASE '+ @dbName
+ N' SET SINGLE_USER'
+ N' WITH ROLLBACK IMMEDIATE;'
+ N' RESTORE DATABASE ' + @dbName
+ N' FROM DISK = @BakFilePath'
+ N' WITH NORECOVERY, REPLACE;'
+ N' RESTORE DATABASE ' + @dbName
+ N' FROM DISK = @DiffFilePath'
+ N' WITH NORECOVERY;'
+ N' RESTORE DATABASE ' + @dbName
+ N' FROM DISK = @TrnFilePath'
+ N' WITH RECOVERY, STOPAT = @RecoveryTime;'
+ N' ALTER DATABASE ' + @dbName
+ N' SET MULTI_USER;
'
EXEC sp_executesql @strSQL",DB_Name, BakFile.FullName, DiffFile.FullName, TrnFile.FullName, Point_In_Time);
你可以显示它的“抱怨”关于dbName值的整个输出吗? –
目前试图找出如何将我的程序的输出发送到屏幕和文件...在Linux上很容易做到哈哈。 –
c#console程序? console.writeline(),如果你导入system.windows.forms,你可以使用messagebox.show(),system.file.io,你可以使用File.WriteAllText(filepath)。您还可以在命令行运行程序时使用语法(如c:\ program.exe> results.txt)将其保存到文件中。 – Matt