Vous êtes sur la page 1sur 7

ⓘ Optimized by Google just now View original

https://stackoverflow.com/questions/50254535/how-to-restore-a-sql-server-backup-in-net-core

Stack Overflow Menu

1 How to restore a SQL Server backup in .NET Core

I want to restore a SQL Server database ( .bak ) using .NET Core. Here is my empty website on GitHub
so you can see the current config.

Restoring a database is fairly simple in the full .NET Framework - as can bee seen here.

Is there a way to do it from .NET Core directly, or will I need to reference the .NET Framework and use a
.NET Framework class library?

No matter how I try, I can't get it to work.

EDIT

I tried adding SQLManagementObject, but can't. I'm on .NET Core 2.0.

EDIT 2

Our old projects are largely ADO.NET. They use (extensively) the following DLL's that I cannot bring into
my .NET Core Project:

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

share improve this question

HockeyJ asked
May 9 at 13:23
6,870 ● 7 ● 50 ● 76

edited
May 24 at 8:17

This question has an open bounty worth +50 reputation from HockeyJ ending in 18 hours.
The question is widely applicable to a large audience. A detailed canonical answer is required to address all the concerns.

I am looking to start moving us over to .NET Core, but need to migrate (or at least integrate) a lot of ADO.NET code on the old
.NET framework. The first task is simply restoring a database with a new name, but I can't do it. Please help.

Did you try to run that code under .NET Core? What happened? If you didn't try, why are you asking us? – Camilo Terevinto May 9
at 13:25
1 I don't think you have searched quite enough: nuget.org/packages/Microsoft.SqlServer.SqlManagementObjects (note the
".NETCoreApp 2.0" under dependencies) – Camilo Terevinto May 9 at 13:30

4 When in doubt you can just issue the restore database sql command – BugFinder May 9 at 13:32

3 Use the T-SQL interface instead: docs.microsoft.com/en-us/sql/t-sql/statements/… – Ben May 9 at 14:42

2 I think, Ben has your answer: create a Command, glue together a RESTORE DATABASE name_of_db FROM DISK =
'where_ever.bak' and execute that. – ralf.w.May 25 at 13:29

show 4 more comments

3 Answers order by votes

1 In .NetCore to backup/restore SQL Server database you can use common ADO.NET SqlConnection and
consult with

RESTORE Statements (T-SQL)

BACKUP Statements (T-SQL)

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.MSSQ
RestoreDatabase("test", @"C:\Program Files\Microsoft SQL Server\MSSQL13.MSS
}

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, NOUNLO
ALTER DATABASE [{databaseName}] SET MULTI_USER;";

SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStrin


{
DataSource = "localhost",
InitialCatalog = "master",
IntegratedSecurity = true
};
using (SqlConnection connection = new SqlConnection(connectionStringBuilder
{
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'{backu

SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStrin


{
DataSource = "localhost",
InitialCatalog = "master",
IntegratedSecurity = true
};
using (SqlConnection connection = new SqlConnection(connectionStringBuilder
{
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, SqlInfoMessageEventAr


{
Console.WriteLine(e.Message);
}
}
}

To RESTORE a database with new name for example newtest, you need execute next statement

RESTORE DATABASE [newtest]


FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\t
MOVE N'test' TO N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\
MOVE N'test_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\D
share improve this answer
Dmitry Kolchev answered
301●1●5 May 26 at 8:30
edited
May 26 at 8:42

0 It looks like the answer is in the comments:

https://www.nuget.org/packages/Microsoft.SqlServer.SqlManagementObjects in the Dependencies


section lists ".NETCoreApp 2.0" meaning it is a .NET Core assembly. Since it depends on
https://www.nuget.org/packages/System.Data.SqlClient/ and that depends on
https://www.nuget.org/packages/Microsoft.Win32.Registry/ it'll only work on Windows, though it will
work on .NET Core.

Alternatively, use T-SQL statements executed through SqlCommand.


share improve this answer
robrich answered
9,989●4●19●46 yesterday

0 You should not use SMO, SMO is created for those that would like to manage SQL server in a
"manage SQL server type application", you're bound to run into versioning issues that you would not
have when using simple TSQL commands. TSQL commands work quite well on .net Core.

One thing I'd like to mention is that you're opening your application to some troubling permissions.

1. you need to set your database into single user mode before you can restore your database
when you do that your web-user will be able to continue doing what it is doing (update, delete,
insert) all this will alter the transaction log and will mess-up something (opt-out of some legal
option, do a payment, cancel something...).
2. Are you happy with the web user being able to set it in single user mode or restore a database,
could be quite malicious?
3. The web user will need elevated privileges to be able to pull this off, I can imagine someone
using this to backup a database to a public folder and just grab if of your web server. Our
Firewall logs show this type of attack vector on a daily basis ("they" do not know we do not use
this).

if you need to restore your database you perhaps pass this over to another task set up for this. you
can then have this "pooling task" deal with this.

Let assume you accept my concerns mentioned above (not a compleat list) and you would entertain
the idea that you would like to offload this I would suggest you use a Task in SQL server for this. You
can schedule these tasks to run ever ... second/ minute/ day even loop them.

You can have "N" steps in a task, 1 Step you use to "test for the restore condition" he following steps
you use to do the restore in a managed way, when you're done you update a log/ send a mail etc.

When using a task you can run it using a user with the appropriate rights and when setting the
database in single user mode your website will lose its connection and will be forced to wait for the
restore job to restore the database state.

For you to be able to use SQL jobs you will need to make sure that this is activated on the server.

As per the content of your task, the TSQL statement if you would like to could look something like
this, please note you need to validate that the backup file reported by SQL server actually exists, this
used master.sys.xp_cmdshell for that:

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

A safer way to do this is to query the server and hope the location is valid:

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;

both methods will fail if the source is on tape or hosted in an Amazon or Microsoft cloud.
share improve this answer
Computer Aided Trading Systems answered
526●2●9 5 hours ago

Your Answer

Body

Add picture

Log in

OR

Name

Email

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and
that your continued use of the website is subject to these policies.
Post Your Answer

meta chat tour help blog privacy policy legal contact us full site

Download the Stack Exchange Android app

2018 Stack Exchange, Inc

Stack Exchange Stack Overflow


sign up log in

Questions Jobs
Tags Users
Badges Ask

c# sql-server
.net-core