最近在做一个数据采集模块,遇到这样一个场景,就是需要将数据库备份文件还原到指定数据库实例下再采集数据。本机测试都没有问题,可一拿到真实环境中测试却发现了一个很大的Bug。所有的数据库都还原不上,很纠结。因为我本以为SQL SERVER 会还原到默认路径下,其实不然。
当我拿到真实数据库备份文件时,我首先在数据库中运行 restore database RestoreDbName from disk ='H:\DBFolder\Db_Back' ,执行结果如下:
到现在我依然不知道是怎么回事,因为我自己创建的数据库再还原是好使的。怎么会这样?一个意外让我发现原来我建的数据库是在数据库实例默认的路径下,而真实数据库备份文件则不是,它的路径是客户机器上的,肯定不一样。为了验证这个发现,我做了如下的工作。
第一步:创建数据库,create database TestDb 。
第二步:备份数据库。
第三步:直接还原数据库,restore database RestoreDbName from disk ='I:\TestDatabase' ,执行成功。
第四步:还原数据库,这时候我不是采用默认还原,而是将数据库还原到系统的另一个路径下,代码如下:
restore database RestoreDbName from disk ='I:\TestDatabase' with replace, move 'TestDb' to 'H:\DBFolder\RestoreDbName_Data.mdf', move 'TestDb_log' to 'H:\DBFolder\RestoreDbName_Log.ldf'
执行结果:
第五步:再次备份数据库RestoreDbName。备份后我们用 filelistonly 可以看到当前数据库备份文件的备份路径( restore filelistonly from disk = 'I:\RestoreDb' ), 执行后结果如下:
从这里我们可以看到当前数据库备份文件的真实物理路径。
第六步:当我再次执行 restore database RestoreDbName from disk ='I:\RestoreDb' ,执行错误。出现了和真实环境一样的错误。原来如上文所述那样,数据库备份文件在还原时,如果当前数据库实例的默认路径和数据库备份文件不相符时需要通过move来解决,而不能单纯的 Restore。
于是我又重新写了一下数据库备份文件还原的相关方法,如下所示。通过这个方法就能简单的实现数据库备份文件还原了。
/// <summary>
/// 还原数据库文件
/// </summary>
/// <param name="basePath">电子账簿所在根目录</param>
/// <param name="fileName">数据库备份文件名称</param>
/// <param name="databaseName">需要还原的数据库名称</param>
/// <param name="conn">数据库连接</param>
private bool RestoreDataBase(string basePath, string fileName, string databaseName, SqlConnection conn)
{
SqlCommand command = null;
try
{
string restoreStr = string.Empty;
string getLogicFileName = string.Format("restore filelistonly from disk ='{0}'", Path.Combine(basePath, fileName));
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(getLogicFileName, conn);
da.Fill(ds);
if (ds.Tables == null || ds.Tables[0].Rows.Count == 0) return false;
foreach (DataRow dr in ds.Tables[0].Rows)
{
//查找数据库逻辑文件名称
if ("D".Equals(dr["Type"].ToString()))
restoreStr += string.Format("move '{0}' to '{1}',", dr["LogicalName"].ToString(), Path.Combine(basePath, databaseName) + "_Data.mdf");
//查找数据库日志文件名称
else if ("L".Equals(dr["Type"].ToString()))
restoreStr += string.Format("move '{0}' to '{1}',", dr["LogicalName"].ToString(), Path.Combine(basePath, databaseName) + "_Log.ldf");
}
if (string.IsNullOrEmpty(restoreStr))
restoreStr = string.Format("restore database {0} from disk ='{1}'", databaseName, Path.Combine(basePath, fileName));
else
{
restoreStr = string.Format("restore database {0} from disk ='{1}' with replace,", databaseName, Path.Combine(basePath, fileName)) + restoreStr.TrimEnd(',');
}
command = new SqlCommand(restoreStr, conn);
conn.Open();
command.ExecuteNonQuery();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
conn.Close();
}
}