首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在.NET核心中还原Server备份

如何在.NET核心中还原Server备份
EN

Stack Overflow用户
提问于 2018-05-09 13:23:49
回答 3查看 5.9K关注 0票数 10

我希望使用Server核心还原Server数据库(.bak)。这是我在GitHub上的空网站,所以你可以看到当前的配置。

在完整的.NET框架中,恢复数据库相当简单--可以看到这里

是否有一种直接从.NET核心执行此操作的方法,或者我是否需要引用.NET框架并使用.NET框架类库?

不管我怎么努力,我都不能让它起作用。

编辑

我试着添加SQLManagementObject,但做不到,我正在使用.NET Core2.0。

编辑2

我们的旧项目很大程度上是ADO.NET。它们(广泛地)使用以下DLL,我无法将其引入到.NET核心项目中:

  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.SmoExtended
  • Microsoft.SqlServer.Management.Sdk.Sfc
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-26 08:30:21

更新:使用.Net Core2.0,您可以使用Microsoft.SqlServer.SqlManagementObjects (140.17265.0)。Server管理对象(SMO)框架您可以在Windows和Linux下使用SMO。

Microsoft.SqlServer.SqlManagementObjects依赖于System.Data.SqlClient (4.5.0)

简单的SMO备份示例:

代码语言:javascript
复制
            ServerConnection serverConnection = new ServerConnection("192.168.1.1", "user", "password");
            Server server = new Server(serverConnection);
            Database database = server.Databases["AdventureWorks"];
            Backup backup = new Backup();
            backup.Action = BackupActionType.Database;
            backup.BackupSetDescription = "AdventureWorks - full backup";
            backup.BackupSetName = "AdventureWorks backup";
            backup.Database = "AdventureWorks";

            BackupDeviceItem deviceItem = new BackupDeviceItem("AdventureWorks_Full_Backup.bak", DeviceType.File);
            backup.Devices.Add(deviceItem);
            backup.Incremental = false;
            backup.LogTruncation = BackupTruncateLogType.Truncate;
            backup.SqlBackup(server);

在.NetCore中,您可以使用常见的ADO.NET、SqlConnection和SqlCommand对象来备份/还原Server数据库。若要自定义备份/还原,需要了解T备份/还原语句的语法。请咨询

还原语句(T)

备份语句(T)

代码语言:javascript
复制
using System;
using System.Data;
using System.Data.SqlClient;

namespace BackupRestore
{
    class Program
    {
        static void Main(string[] args)
        {
            BackupDatabase("test", @"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\test.bak");
            RestoreDatabase("test", @"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\test.bak");
        }

        private static void RestoreDatabase(string databaseName, string backupPath)
        {
            string commandText = $@"USE [master];
    ALTER DATABASE [{databaseName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    RESTORE DATABASE [{databaseName}] FROM DISK = N'{backupPath}' WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 5;
    ALTER DATABASE [{databaseName}] SET MULTI_USER;";

            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder
            {
                DataSource = "localhost",
                InitialCatalog = "master",
                IntegratedSecurity = true
            };
            using (SqlConnection connection = new SqlConnection(connectionStringBuilder.ConnectionString))
            {
                connection.Open();
                connection.InfoMessage += Connection_InfoMessage;
                using (SqlCommand command = connection.CreateCommand())
                {
                    command.CommandText = commandText;
                    command.CommandType = CommandType.Text;
                    command.ExecuteNonQuery();
                }
            }
        }

        private static void BackupDatabase(string databaseName, string backupPath)
        {
            string commandText = $@"BACKUP DATABASE [{databaseName}] TO DISK = N'{backupPath}' WITH NOFORMAT, INIT, NAME = N'{databaseName}-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10";

            SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder
            {
                DataSource = "localhost",
                InitialCatalog = "master",
                IntegratedSecurity = true
            };
            using (SqlConnection connection = new SqlConnection(connectionStringBuilder.ConnectionString))
            {
                connection.Open();
                connection.InfoMessage += Connection_InfoMessage;
                using (SqlCommand command = connection.CreateCommand())
                {
                    command.CommandText = commandText;
                    command.CommandType = CommandType.Text;
                    command.ExecuteNonQuery();
                }
            }
        }

        private static void Connection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

要还原具有新名称的数据库(例如newtest ),需要执行next语句

代码语言:javascript
复制
RESTORE DATABASE [newtest] 
FROM  DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\test.bak' WITH  FILE = 1,  
MOVE N'test' TO N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\newtest.mdf',  
MOVE N'test_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\newtest_log.ldf',  NOUNLOAD,  STATS = 5
票数 15
EN

Stack Overflow用户

发布于 2018-05-30 07:28:46

您不应该使用SMO,SMO是为那些想要在“管理SQL服务器类型应用程序”中管理SQL服务器的人创建的,您肯定会遇到在使用简单TSQL命令时不会遇到的版本控制问题。TSQL命令在.net核心上运行得很好。

我想提到的一件事是,您正在向某些令人不安的权限打开应用程序。

  1. 在恢复数据库之前,您需要将数据库设置为单用户模式,这样web用户就可以继续做它正在做的事情(更新、删除、插入)--所有这些都会改变事务日志,并会搞乱一些事情(选择退出某些法律选项、进行支付、取消某些事情.)。
  2. 您对web用户能够在单用户模式下设置它或恢复数据库感到满意吗?
  3. 网络用户将需要提升的特权才能做到这一点,我可以想象有人使用这个备份数据库到公用文件夹,只要抓取如果你的web服务器。我们的防火墙日志每天都显示这种类型的攻击矢量(“他们”不知道我们不使用这个)。

如果需要还原数据库,则可能将其传递给为此设置的另一个任务。然后,您可以让这个“池任务”来处理这个问题。

假设您接受了我上面提到的问题(不是完成列表),并且考虑到您想要卸载这个问题,我建议您在SQL server中使用一个任务来完成这个任务。你可以安排这些任务.第二/分钟/一天甚至循环它们。

您可以在一个任务中有"N“步骤,用于”测试恢复条件“的步骤--他遵循了以托管方式执行还原的步骤,当您完成任务时,更新日志/发送邮件等等。

使用任务时,您可以使用具有适当权限的用户运行该任务,并且在单用户模式下设置数据库时,您的网站将失去其连接,并将被迫等待还原作业恢复数据库状态。

为了能够使用SQL作业,您需要确保在服务器上激活了SQL作业。

根据任务的内容,TSQL语句--如果您想要这样做--请注意,您需要验证由SQL server报告的备份文件是否确实存在,为此使用了master.sys.xp_cmdshell:

代码语言:javascript
复制
USE Master; 
GO  
SET NOCOUNT ON 

-- 1 - Variable declaration 
DECLARE @dbName sysname 
DECLARE @backupPath NVARCHAR(500) 
DECLARE @cmd NVARCHAR(500) 
DECLARE @fileList TABLE (backupFile NVARCHAR(255)) 
DECLARE @lastFullBackup NVARCHAR(500) 
DECLARE @lastDiffBackup NVARCHAR(500) 
DECLARE @backupFile NVARCHAR(500) 

-- 2 - Initialize variables 
SET @dbName = 'Customer' 
SET @backupPath = 'D:\SQLBackups\' 

-- 3 - get list of files 
SET @cmd = 'DIR /b "' + @backupPath + '"'

INSERT INTO @fileList(backupFile) 
EXEC master.sys.xp_cmdshell @cmd 

-- 4 - Find latest full backup 
SELECT @lastFullBackup = MAX(backupFile)  
FROM @fileList  
WHERE backupFile LIKE '%.BAK'  
   AND backupFile LIKE @dbName + '%' 

SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''  
       + @backupPath + @lastFullBackup + ''' WITH NORECOVERY, REPLACE' 
PRINT @cmd 

-- 4 - Find latest diff backup 
SELECT @lastDiffBackup = MAX(backupFile)  
FROM @fileList  
WHERE backupFile LIKE '%.DIF'  
   AND backupFile LIKE @dbName + '%' 
   AND backupFile > @lastFullBackup 

-- check to make sure there is a diff backup 
IF @lastDiffBackup IS NOT NULL 
BEGIN 
   SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''  
       + @backupPath + @lastDiffBackup + ''' WITH NORECOVERY' 
   PRINT @cmd 
   SET @lastFullBackup = @lastDiffBackup 
END 

-- 5 - check for log backups 
DECLARE backupFiles CURSOR FOR  
   SELECT backupFile  
   FROM @fileList 
   WHERE backupFile LIKE '%.TRN'  
   AND backupFile LIKE @dbName + '%' 
   AND backupFile > @lastFullBackup 

OPEN backupFiles  

-- Loop through all the files for the database  
FETCH NEXT FROM backupFiles INTO @backupFile  

WHILE @@FETCH_STATUS = 0  
BEGIN  
   SET @cmd = 'RESTORE LOG [' + @dbName + '] FROM DISK = '''  
       + @backupPath + @backupFile + ''' WITH NORECOVERY' 
   PRINT @cmd 
   FETCH NEXT FROM backupFiles INTO @backupFile  
END 

CLOSE backupFiles  
DEALLOCATE backupFiles  

-- 6 - put database in a useable state 
SET @cmd = 'RESTORE DATABASE [' + @dbName + '] WITH RECOVERY' 
PRINT @cmd 

一种更安全的方法是查询服务器并希望该位置是有效的:

代码语言:javascript
复制
SELECT
    bs.database_name,
    bs.backup_start_date,
    bmf.physical_device_name
FROM
    msdb.dbo.backupmediafamily bmf
    JOIN
    msdb.dbo.backupset bs ON bs.media_set_id = bmf.media_set_id
WHERE
    bs.database_name = 'MyDB'
ORDER BY
    bmf.media_set_id DESC;

如果源在磁带上或托管在亚马逊微软云中,这两种方法都将失败。

票数 2
EN

Stack Overflow用户

发布于 2018-05-28 23:44:33

答案似乎就在评论中:

依赖项部分中的https://www.nuget.org/packages/Microsoft.SqlServer.SqlManagementObjects列出了".NETCoreApp 2.0“,这意味着它是一个.NET核心程序集。由于它依赖于https://www.nuget.org/packages/System.Data.SqlClient/,而这取决于https://www.nuget.org/packages/Microsoft.Win32.Registry/,所以它只能在.NET上工作,尽管它将在.NET核心上工作。

或者,使用通过SqlCommand执行的T语句。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50254535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档