Выполнение сценария SQL (Transact- SQL) с помощью HostedService [ASP. NET CORE 3.1.0 C #] - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь запустить скрипт, который сохраняет мою базу данных с помощью созданной мной службы:

Вот код моей службы:

using Microsoft.Extensions.Logging;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System;
using System.Data.SqlClient;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace TEST_BACKUP_DB
{    
    internal interface IScopedDBService
    {
        Task DoWork(CancellationToken stoppingToken);
    }

    public class ScopedDBService : IScopedDBService
    {
            private int executionCount = 0;
            private readonly ILogger _logger;

            public ScopedDBService(ILogger<ScopedDBService> logger)
            {
                _logger = logger;

            }

            public async Task DoWork(CancellationToken stoppingToken)
            {

                while (!stoppingToken.IsCancellationRequested)
                {

                string sqlConnectionString = 
                    @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\user1\Documents\DB_TEST.mdf;Integrated Security=True;Connect Timeout=30";

                string script = File.ReadAllText(@"myscript.sql");

                try {

                    SqlConnection conn = new SqlConnection(sqlConnectionString);

                    Server server = new Server(new ServerConnection(conn));

                    server.ConnectionContext.ExecuteNonQuery(script);

                    executionCount++;

                    _logger.LogInformation(
                        "Saving DB count: {Count}", executionCount);
                }
                catch(Exception e)
                {
                    _logger.LogInformation("Error not saved: {e}",e);
                }

                await Task.Delay(5000, stoppingToken);
                }
            }
        }
}

Чтобы использовать эту службу, я Я использую следующий код:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using static TEST_BACKUP_DB.ScopedDBService;

namespace TEST_BACKUP_DB
{
    public class ConsumeScopedServiceHostedService : BackgroundService
    {
        private readonly ILogger<ConsumeScopedServiceHostedService> _logger;

        public ConsumeScopedServiceHostedService(IServiceProvider services,
            ILogger<ConsumeScopedServiceHostedService> logger)
        {
            Services = services;
            _logger = logger;
        }

        public IServiceProvider Services { get; }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation(
                "Consume Scoped Service Hosted Service running.");

            await DoWork(stoppingToken);
        }

        private async Task DoWork(CancellationToken stoppingToken)
        {
            _logger.LogInformation(
                "Consume Scoped Service Hosted Service is working.");

            using (var scope = Services.CreateScope())
            {
                var scopedProcessingService =
                    scope.ServiceProvider
                        .GetRequiredService<IScopedDBService>();

                await scopedProcessingService.DoWork(stoppingToken);
            }
        }

        public override async Task StopAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation(
                "Consume Scoped Service Hosted Service is stopping.");

            await Task.CompletedTask;
        }
    }
}

Я зарегистрировал их в классе Startup.cs следующим образом

public void ConfigureServices(IServiceCollection services)
        {
            services.AddHostedService<ConsumeScopedServiceHostedService>();
            services.AddScoped<IScopedDBService, ScopedDBService>();
        }

Мой файл Transact- SQL (myscript. sql) это:

BACKUP DATABASE [DB_TEST]
TO DISK = 'D:\BACKUPS\_1.BAK'
MIRROR TO DISK = 'D:\BACKUPS\_2.BAK'
WITH FORMAT
GO

Я проверил выделенный сервис без этой части кода, и он работает нормально:

Server server = new Server(new ServerConnection(conn));

server.ConnectionContext.ExecuteNonQuery(script);

Когда я запускаю свое приложение, оно дает мне следующее исключение:

enter image description here

Когда я отлаживаю, я получаю это на атрибуте сервера:

ActiveDirectory = 'server.ActiveDirectory' вызвал исключение введите 'Microsoft.SqlServer.Management.Smo.UnsupportedFeatureException'

Я установил пакет nugetPackage: Microsoft.SqlServer.SqlManagementObject для использования класса сервера, возникает ли проблема? У кого-нибудь есть альтернативы или решения?

1 Ответ

2 голосов
/ 31 марта 2020

SMO не требуется для запуска пакета T SQL, и все ошибки BACKUP / RESTORE будут находиться в коллекции SqlException.Errors. Вы видите только последний.

EG

    using (SqlConnection conn = new SqlConnection(sqlConnectionString))
    {
        conn.Open();

        var cmd = conn.CreateCommand();

        cmd.CommandText = script;
        try
        {
            cmd.ExecuteNonQuery();
        }
        catch (SqlException ex)
        {
            foreach (var e in ex.Errors)
            {
                Console.WriteLine(e.ToString());
            }
            throw;
         }
    }

выведет причину root, что-то вроде:

Microsoft.Data.SqlClient.SqlError: Database 'xxxxx' does not exist. Make sure that the name is entered correctly.
Microsoft.Data.SqlClient.SqlError: BACKUP DATABASE is terminating abnormally.
...