23

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.

照合を設定する方法を教えてもらえますか?

4

8 に答える 8

7

EFCore 2.1での私の解決策は、SqlServerMigrationsSqlGenerator から派生させ、Generate(SqlServerCreateDatabaseOperation, IModel, MigrationCommandListBuilder) をオーバーライドすることでした。

    internal class CustomSqlServerMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
    {
        internal const string DatabaseCollationName = "SQL_Latin1_General_CP1_CI_AI";

        public CustomSqlServerMigrationsSqlGenerator(
            MigrationsSqlGeneratorDependencies dependencies,
            IMigrationsAnnotationProvider migrationsAnnotations)
        : base(dependencies, migrationsAnnotations)
        {
        }

        protected override void Generate(
            SqlServerCreateDatabaseOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            base.Generate(operation, model, builder);

            if (DatabaseCollationName != null)
            {
                builder
                    .Append("ALTER DATABASE ")
                    .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name))
                    .Append(" COLLATE ")
                    .Append(DatabaseCollationName)
                    .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator)
                    .EndCommand(suppressTransaction: true);
            }
        }
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.ReplaceService<IMigrationsSqlGenerator, CustomSqlServerMigrationsSqlGenerator>();
    }

次に、IMigrationsSqlGenerator サービスを置き換えて DbContext で使用します。

public class MyDbContext : DbContext
{
    //...

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.ReplaceService<IMigrationsSqlGenerator, CustomSqlServerMigrationsSqlGenerator>();
    }

    //...
}
于 2019-03-21T10:04:05.723 に答える
5

私はしばらく前に同じ問題を抱えていました。可能な解決策:

  1. EF はサーバーの既定の照合順序を使用してデータベースを作成しているように見えるので、できることの 1 つはそれを変更することです。
  2. メソッド内でデータベースの照合を変更することはできませんがSeed()、テーブルの個々の列の照合を変更することはできます (注: テーブルの照合などはなく、テーブルの列に関連しています)。各列の照合を個別に変更する必要があります。
  3. 移行を使用している場合は、Up()メソッド内でテーブルの列の照合を変更できます。

メソッドを使用しているため、メソッドSeed()内で次のことをお勧めします (必要に応じて変更します) 。Seed()

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

それが役立つことを願っています。

于 2014-04-06T15:00:30.903 に答える
1

現在のバージョンの EF (EF6) を使用することは不可能です。ただし、少なくとも EF6+ は既存のデータベースで動作するようになりました。データベースがデプロイ スクリプト (既定の照合順序を含む) によって既に作成されており、EF6 が既存のデータベース (正しい既定の照合順序を使用) で動作するように、展開シナリオを変更しました。

コード内でデータベースを作成する必要があり、EF 以外を使用できない場合 (たとえば、ADO.NET を使用してデータベースを作成できない場合)、seliosalex の回答を使用する必要があります。それが私たちが思いついた唯一の解決策ですが、私のコメントを参照してください。それを正しく行うには多くの作業が必要です。

于 2014-04-06T15:26:54.333 に答える
0

EF 5は、Code Firstを使用して既存のデータベースに欠落しているテーブルを作成できるようになりました。そのため、CFを実行する前に、空のデータベースを作成して照合を正しく設定できます。

于 2012-11-09T11:17:47.827 に答える