Миграция EF Core на новый сервер SQL - PullRequest
0 голосов
/ 13 февраля 2020

Я пытаюсь создать консольное приложение миграции, которое может запускаться с нуля, то есть на только что установленном сервере SQL, включая выделенного пользователя с учетными данными, которым должен быть db_owner.

У меня это работает на PostgreSQL, но мне нужно получить аналогичное решение для SQL Сервера.

Прежде чем я позвоню context.Database.Migrate(), я звоню CheckDatabaseCreated(context.Database, configuration), который в основном делает это:

  1. Пытается соединиться с данной строкой соединения

  2. В случае неудачи он заменяет пользователя и пароль на пароль SA и SA и подключается к мастеру.

  3. Создает логин, если он не существует.

  4. Создает базу данных, если он не существует.

  5. Подключается к вновь созданной базе данных - все еще как SA.

  6. Создает пользователя с логином и добавляет роль db_owner.

  7. Наконец, он пытается снова подключиться, используя исходную строку подключения - это то место, где он не работает.

Использование Heidi SQL, я вижу, что база данных создана, но я могу подключиться только с использованием учетных данных SA.

    private static void CheckDatabaseCreated(DatabaseFacade contextDatabase, IConfiguration configuration)
    {
        bool canConnect;
        try
        {
            canConnect = contextDatabase.CanConnect();
            Console.WriteLine("Database connected succesfully.");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Unable to connect to database: {e.Message}");
            canConnect = false;
        }
        if (!canConnect)
        {
            var builder = new SqlConnectionStringBuilder(configuration["ConnectionString"]);
            var originalUser = builder.UserID;
            var originalPassword = builder.Password;
            var originalDatabase = builder.InitialCatalog;
            builder.UserID = _masterUsername;
            builder.Password = _masterPassword;
            builder.InitialCatalog = "master";
            var login = $"{originalUser}Login";

            SqlConnection conn = new SqlConnection(builder.ConnectionString);
            try
            {
                conn.Open();
                // Check if login exists
                SqlCommand command = new SqlCommand($"SELECT COUNT(*) FROM master.sys.server_principals WHERE name = '{login}'", conn);
                object result = command.ExecuteScalar();
                result = (result == DBNull.Value) ? null : result;
                if (Convert.ToInt32(result) < 1)
                {
                    Console.WriteLine("Login does not exist - creating.");
                    command = new SqlCommand($"CREATE LOGIN [{login}] WITH PASSWORD = N'{originalPassword}', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF", conn);
                    command.ExecuteNonQuery();
                }
                // Check if database exists
                command = new SqlCommand($"SELECT COUNT(*) FROM master.sys.databases WHERE name = '{originalDatabase}'", conn);
                result = command.ExecuteScalar();
                result = (result == DBNull.Value) ? null : result;
                if (Convert.ToInt32(result) < 1)
                {
                    Console.WriteLine("Database does not exist - creating.");
                    command = new SqlCommand($"CREATE DATABASE \"{originalDatabase}\" ", conn);
                    command.ExecuteNonQuery();
                }
                conn.Close();
                // Now connect to the (newly created) database - still as sa.
                builder.InitialCatalog = originalDatabase;
                conn = new SqlConnection(builder.ConnectionString);
                try
                {
                    conn.Open();
                    command = new SqlCommand($"CREATE USER [{originalUser}] FOR LOGIN [{login}]", conn);
                    command.ExecuteNonQuery();

                    command = new SqlCommand($"EXEC sp_addrolemember 'db_owner', '{originalUser}'", conn);
                    command.ExecuteNonQuery();

                    conn.Close();
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Unable to connect to {originalDatabase} database: {e.Message}");
                }
                // Finally try to connect as the user created above.
                builder = new SqlConnectionStringBuilder(configuration["ConnectionString"]);
                conn = new SqlConnection(builder.ConnectionString);
                try
                {
                    conn.Open();
                }
                catch (Exception e)
                {
                    // This is where it fails.
                    Console.WriteLine($"Unable to connect to database: {e.Message}");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine($"Unable to connect to database: {e.Message}");
            }
        }
    }

1 Ответ

0 голосов
/ 13 февраля 2020

User ID в строке подключения к серверу SQL относится к логину или пользователю в автономной базе данных.

Итак, ваша проблема здесь:

   var login = $"{originalUser}Login";

Этот логин не тот, на который есть ссылка в вашей строке подключения. Нет причин, по которым Логин и Пользователь базы данных должны иметь разные имена. Так что сделайте их одинаковыми:

   var login = originalUser;
...