Özel Geçiş İşlemleri

MigrationBuilder API'si, geçiş sırasında birçok farklı türde işlem gerçekleştirmenize olanak tanır, ancak çok kapsamlı değildir. Ancak API, kendi işlemlerinizi tanımlamanızı sağlayan genişletilebilir bir özelliktir. API'yi genişletmenin iki yolu vardır: yöntemini kullanma Sql() veya özel MigrationOperation nesneler tanımlama.

Bunu göstermek için, her yaklaşımı kullanarak veritabanı kullanıcısı oluşturan bir işlem uygulamaya bakalım. Geçişlerimizde aşağıdaki kodun yazılmasını etkinleştirmek istiyoruz:

migrationBuilder.CreateUser("SQLUser1", "Password");

MigrationBuilder.Sql() Kullanma

Özel işlem gerçekleştirmenin en kolay yolu çağıran MigrationBuilder.Sql()bir uzantı yöntemi tanımlamaktır. Aşağıda uygun Transact-SQL'i oluşturan bir örnek verilmiştir.

public static OperationBuilder<SqlOperation> CreateUser(
    this MigrationBuilder migrationBuilder,
    string name,
    string password)
    => migrationBuilder.Sql($"CREATE USER {name} WITH PASSWORD '{password}';");

Bahşiş

Deyimin EXEC SQL toplu işleminde ilk veya tek olması gerektiğinde işlevini kullanın. Ayrıca, başvuruda bulunılan sütunlar şu anda bir tabloda mevcut olmadığında oluşabilecek bir kez etkili geçiş betiklerindeki ayrıştırıcı hatalarına geçici bir çözüm bulmak gerekebilir.

Geçişlerinizin birden çok veritabanı sağlayıcısını desteklemesi gerekiyorsa özelliğini kullanabilirsiniz MigrationBuilder.ActiveProvider . Burada hem Microsoft SQL Server hem de PostgreSQL'i destekleyen bir örnek verilmiştir.

public static OperationBuilder<SqlOperation> CreateUser(
    this MigrationBuilder migrationBuilder,
    string name,
    string password)
{
    switch (migrationBuilder.ActiveProvider)
    {
        case "Npgsql.EntityFrameworkCore.PostgreSQL":
            return migrationBuilder
                .Sql($"CREATE USER {name} WITH PASSWORD '{password}';");

        case "Microsoft.EntityFrameworkCore.SqlServer":
            return migrationBuilder
                .Sql($"CREATE USER {name} WITH PASSWORD = '{password}';");
    }

    throw new Exception("Unexpected provider.");
}

Bu yaklaşım yalnızca özel işleminizin uygulanacağı her sağlayıcıyı biliyorsanız çalışır.

MigrationOperation Kullanma

Özel işlemi SQL'den ayrıştırmak için, bunu temsil etmek için kendi MigrationOperation işleminizi tanımlayabilirsiniz. Daha sonra işlem, oluşturulacak uygun SQL'i belirleyebilmesi için sağlayıcıya geçirilir.

public class CreateUserOperation : MigrationOperation
{
    public string Name { get; set; }
    public string Password { get; set; }
}

Bu yaklaşımla, uzantı yönteminin bu işlemlerden birini öğesine MigrationBuilder.Operationseklemesi gerekir.

public static OperationBuilder<CreateUserOperation> CreateUser(
    this MigrationBuilder migrationBuilder,
    string name,
    string password)
{
    var operation = new CreateUserOperation { Name = name, Password = password };
    migrationBuilder.Operations.Add(operation);

    return new OperationBuilder<CreateUserOperation>(operation);
}

Bu yaklaşım, her sağlayıcının kendi hizmetinde bu işlem IMigrationsSqlGenerator için SQL oluşturmayı bilmesini gerektirir. Yeni işlemi işlemek için SQL Server oluşturucusunun geçersiz kılınan bir örnek aşağıda verilmiştir.

public class MyMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
{
    public MyMigrationsSqlGenerator(
        MigrationsSqlGeneratorDependencies dependencies,
        ICommandBatchPreparer commandBatchPreparer)
        : base(dependencies, commandBatchPreparer)
    {
    }

    protected override void Generate(
        MigrationOperation operation,
        IModel model,
        MigrationCommandListBuilder builder)
    {
        if (operation is CreateUserOperation createUserOperation)
        {
            Generate(createUserOperation, builder);
        }
        else
        {
            base.Generate(operation, model, builder);
        }
    }

    private void Generate(
        CreateUserOperation operation,
        MigrationCommandListBuilder builder)
    {
        var sqlHelper = Dependencies.SqlGenerationHelper;
        var stringMapping = Dependencies.TypeMappingSource.FindMapping(typeof(string));

        builder
            .Append("CREATE USER ")
            .Append(sqlHelper.DelimitIdentifier(operation.Name))
            .Append(" WITH PASSWORD = ")
            .Append(stringMapping.GenerateSqlLiteral(operation.Password))
            .AppendLine(sqlHelper.StatementTerminator)
            .EndCommand();
    }
}

Varsayılan geçişler sql generator hizmetini güncelleştirilmiş olanla değiştirin.

protected override void OnConfiguring(DbContextOptionsBuilder options)
    => options
        .UseSqlServer(_connectionString)
        .ReplaceService<IMigrationsSqlGenerator, MyMigrationsSqlGenerator>();