Установить сопоставление базы данных в 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.
Кто-нибудь может посоветовать, как я могу настроить сортировку?
Ответы
Ответ 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. Тем не менее, это единственное решение, которое мы придумали, чтобы увидеть мой комментарий, это большая работа, чтобы сделать это правильно.