GreysonTyrus
GreysonTyrus

Reputation: 779

C# restore database with microsoft.sqlserver.management.smo 5(access denied)

I am trying to restore a db with Microsoft.SqlServer.Management.Smo but I keep getting access denied errors.

I have set up the service user for the instance (MSSQL$LOCAL2016) with full access rights to the folder.

The folder is the default folder for the instance (although the same cannot be said when I move to production).

I create the folders within C#

rstDatabase.SqlRestore(sqlServer);

fails with the error:

The operating system returned the error '5(Access is denied.)' while attempting 'RestoreContainer::ValidateTargetForCreation' on 'C:\Database\Rates.setuptest\Data'.
File 'RateUploader' cannot be restored to 'C:\Database\Rates.setuptest\Data'. Use WITH MOVE to identify a valid location for the file.
The operating system returned the error '5(Access is denied.)' while attempting 'RestoreContainer::ValidateTargetForCreation' on 'C:\Database\Rates.setuptest\Logs'.
File 'RateUploader_log' cannot be restored to 'C:\Database\Rates.setuptest\Logs'. Use WITH MOVE to identify a valid location for the file.
Problems were identified while planning for the RESTORE statement. Previous messages provide details.
RESTORE DATABASE is terminating abnormally.

I have changed the folder permissions even so far as to allow 'everyone' full access

I have changed the service login to local service and allowed access to local directory

I am fresh out of ideas

Here is the code, but it's pretty standard

    public static IEnumerable<RestoreDatabaseResponse> RestoreDatabase(String databaseName)
    {
        var eventQueue = new Queue<RestoreDatabaseResponse>();
        var counter = 0;

        MySqlConnectionStringBuilder stringBuilder = new MySqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["adminSqlAccess"].ConnectionString);

        string serverName = stringBuilder.Server, userName = stringBuilder.UserID, password = stringBuilder.Password, 
            pFileLocation = string.Format(ConfigurationManager.AppSettings["dbPath"], databaseName, "Data"), 
            lFileLocation = string.Format(ConfigurationManager.AppSettings["dbPath"], databaseName, "Logs"),
            bakFileLocation = ConfigurationManager.AppSettings["bakDbPath"];

        //permisions are propagating
        if (!Directory.Exists(pFileLocation))
            Directory.CreateDirectory(pFileLocation);
        if (!Directory.Exists(lFileLocation))
            Directory.CreateDirectory(lFileLocation);

        ServerConnection connection = new ServerConnection(serverName, userName, password);
        Server sqlServer = new Server(connection);
        Restore rstDatabase = new Restore();

        //recently added events for reporting.  Still fails without these two
        rstDatabase.Complete += (sender, args) =>
        {
            eventQueue.Enqueue(new RestoreDatabaseResponse
            {
                Command = $"Restore {databaseName}",
                Status = ResponseStatus.Success,
                Detail = "Complete",
                Index = counter++,
                PercentComplete = 100
            });
        };

        rstDatabase.PercentComplete += (sender, args) =>
        {
            eventQueue.Enqueue(new RestoreDatabaseResponse
            {
                Command = $"Restore {databaseName}",
                Status = ResponseStatus.PartialSuccess,
                Detail = "Running",
                Index = counter++,
                PercentComplete = args.Percent
            });
        };

        rstDatabase.Action = RestoreActionType.Database;
        rstDatabase.Database = $"Rates.{databaseName}";

        // I even tried skipping this step.  Still error
        rstDatabase.RelocateFiles.Add(new RelocateFile("RateUploader", pFileLocation));
        rstDatabase.RelocateFiles.Add(new RelocateFile("RateUploader_log", lFileLocation));

        BackupDeviceItem bkpDevice = new BackupDeviceItem(bakFileLocation, DeviceType.File);
        rstDatabase.Devices.Add(bkpDevice);
        rstDatabase.ReplaceDatabase = true;
        RestoreDatabaseResponse errorResponse = null;

        try
        {
            rstDatabase.SqlRestore(sqlServer);
        }
        catch (Exception exception)
        {
            errorResponse = new RestoreDatabaseResponse
            {
                Command = $"Restore {databaseName}",
                Status = ResponseStatus.Failure,
                Detail = exception,
                Index = counter++,
                PercentComplete = 0
            };
        }

        if (errorResponse != null)
        {
            yield return errorResponse;
            yield break;
        }

        while (true)
        {
            if (!eventQueue.Any())
                Thread.Sleep(100);
            else
            {
                var e = eventQueue.Dequeue();
                yield return e;

                if(e.Status== ResponseStatus.Success)
                    yield break;
            }
        }
    }

Upvotes: 1

Views: 942

Answers (1)

GreysonTyrus
GreysonTyrus

Reputation: 779

Oh for Pete's sake!

I omitted the filename from the relocate paths >_<

To be fair, "move" does imply moving from one folder to another, also the error message is identical to the permission issues most people seem to have hit

Upvotes: 1

Related Questions