Подтвердить что ты не робот

Установить сопоставление базы данных в Entity Framework Code-First Initializer

Я хочу установить сортировку по умолчанию для базы данных, когда Entity Framework Code First создает ее.

Я пробовал следующее:

public class TestInitializer<T> : DropCreateDatabaseAlways<T> where T: DbContext
{
    protected override void Seed(T context)
    {
        context.Database.ExecuteSqlCommand("ALTER DATABASE [Test] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
        context.Database.ExecuteSqlCommand("ALTER DATABASE [Test] COLLATE Latin1_General_CI_AS");
        context.Database.ExecuteSqlCommand("ALTER DATABASE [Test] SET MULTI_USER");
    }
}

Кажется, что он запускается нормально, когда SQL Server уже настроен на то же сопоставление по умолчанию Latin1_General_CI_AS.

Но если я укажу другую сортировку, скажем, SQL_Latin1_General_CP1_CI_AS, это не с ошибкой,

System.Data.SqlClient.SqlException: Resetting the connection results in a different 
state than the initial login. The login fails.

Кто-нибудь может посоветовать, как я могу настроить сортировку?

4b9b3361

Ответ 1

Решение с командным перехватчиком

Это определенно возможно, хотя это немного взломать. Вы можете изменить команду CREATE DATABASE с помощью командного перехватчика. Il перехватит все команды, отправленные в базу данных, распознает команду создания базы данных на основе выражения регулярного выражения и изменит текст команды с помощью сортировки.

Перед созданием базы данных

DbInterception.Add(new CreateDatabaseCollationInterceptor("SQL_Romanian_Cp1250_CI_AS_KI_WI"));

Перехватчик

public class CreateDatabaseCollationInterceptor : IDbCommandInterceptor
{
    private readonly string _collation;

    public CreateDatabaseCollationInterceptor(string collation)
    {
        _collation = collation;
    }

    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { }
    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        // Works for SQL Server
        if (Regex.IsMatch(command.CommandText, @"^create database \[.*]$"))
        {
            command.CommandText += " COLLATE " + _collation;
        }
    }
    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { }
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { }
    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { }
    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { }
}

Примечания

Поскольку база данных создается с правильной сортировкой с самого начала, все столбцы будут автоматически наследовать эту сортировку, и после этого вам не будет ALTER.

Помните, что это повлияет на последующее создание базы данных, происходящее внутри домена приложения. Таким образом, вы можете удалить перехватчик после создания базы данных.

Ответ 2

Мне удалось изменить сортировку с помощью пользовательской миграции (EF6). У меня включена автоматическая миграция. Сначала вам нужно удалить свою БД.

  • Создайте код перехода, набрав Add-Migration [YourCustomMigration] в консоли диспетчера пакетов. (Первые шаги миграции)
  • Первый шаг должен создать ваш класс миграции с текущим кодом создания модели в переопределении Up(). Добавьте код ALTER DATABASE ДО кодов создания таблиц, чтобы они были созданы с использованием нужной вам базы данных. Также обратите внимание на флаг suppressTransaction:

public override void Up() { Sql("ALTER DATABASE [YourDB] COLLATE [YourCollation]", suppressTransaction: true); [...Your DB Objects Creation codes here...] }

Каждая команда update-database, выпущенная с этого момента, создает новый класс миграции. Все коды миграции выполняются в порядке.

Ответ 3

У меня была такая же проблема некоторое время назад. Возможные решения:

  • Похоже, что EF создает базу данных с использованием сервера по умолчанию сопоставление, так что одна вещь, которую вы можете сделать, это изменить это.
  • Вы не можете изменить сортировку базы данных в методе Seed() но вы можете изменить сортировку отдельных столбцов для таблицы (ПРИМЕЧАНИЕ: нет такой вещи, как сортировка таблицы, она относится к столбец в таблице). Вам нужно будет изменить сортировку столбцов отдельно.
  • Если вы используете миграции, вы можете изменить столбец таблицы сопоставлений в вашем методе Up().

Поскольку вы используете метод Seed(), я бы предложил следующее (в случае необходимости изменить) в методе Seed():

context.Database.ExecuteSqlCommand(
@"ALTER TABLE MyTable ALTER COLUMN MyColumn NVARCHAR(max) COLLATE MyCollation NOT NULL");

Надеюсь, что это поможет.

Ответ 4

EF 5 теперь поддерживает создание отсутствующих таблиц в существующей базе данных с помощью Code First, поэтому вы можете создать пустую базу данных и установить правильность сопоставления, прежде чем запускать CF на ней.

Ответ 5

Это просто невозможно, используя текущие версии EF (EF6). Однако, по крайней мере, EF6 + теперь может работать с уже существующей базой данных. Мы изменили наш сценарий развертывания таким образом, что база данных уже создана нашим развертыванием script (включая настройку по умолчанию), и пусть EF6 работает с существующей базой данных (с использованием правильной сортировки по умолчанию).

Если вам абсолютно необходимо создать базу данных внутри вашего кода и не использовать ничего, кроме EF (например, вы не можете создать базу данных с помощью ADO.NET), вам нужно обратиться за ответом seliosalex. Тем не менее, это единственное решение, которое мы придумали, чтобы увидеть мой комментарий, это большая работа, чтобы сделать это правильно.