Özel Geçiş İşlemleri

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

Göstermek için, her yaklaşımı kullanarak veritabanı kullanıcısı oluşturan bir işlem uygulamaya bakalım. Geçişlerde aşağıdaki kodu yazmayı etkinleştirmek istiyoruz:

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

MigrationBuilder.Sql() kullanma

Özel bir işlem uygulamanın en kolay yolu, çağıran bir genişletme yöntemi MigrationBuilder.Sql() tanımlamaktır. Burada uygun Transact-SQL.

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

İpucu

Deyimin bir toplu iş içinde ilk veya tek bir EXEC deyim olması SQL kullanın. Ayrıca, başvurulan sütunlar şu anda bir tabloda mevcut değilken ortaya çıkabilir, bir etkili geçiş betikleri içinde ayrıştırıcı hatalarına çözüm olması da gerekli olabilir.

Geçişlerin birden çok veritabanı sağlayıcısını desteklemesi gerekirse özelliğini MigrationBuilder.ActiveProvider kullanabilirsiniz. Hem Microsoft SQL Server hem de PostgreSQL'i destekleyen bir örnek burada vesildir.

private 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 uygulanacak olduğu her sağlayıcıyı biliyorsanız çalışır.

MigrationOperation Kullanma

Özel işlemi özel işlemden SQL, temsil etmek için kendi MigrationOperation işleminizi tanımlayabilirsiniz. İşlem daha sonra sağlayıcıya geçir geçirilebilir, böylece oluşturulecek uygun SQL tarafından belirlenebilirsiniz.

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

Bu yaklaşımda, genişletme yönteminin yalnızca bu işlemlerden birini 'ye eklemesi MigrationBuilder.Operations gerekir.

private 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 hizmetlerinde bu SQL için nasıl veri IMigrationsSqlGenerator oluşturacağız? Burada, yeni işlemi işlemek için SQL Server oluşturucusünü geçersiz kılmaya yönelik bir örnek ve ardından ve ardından bir örnek verİle 3.

internal class MyMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
{
    public MyMigrationsSqlGenerator(
        MigrationsSqlGeneratorDependencies dependencies,
        IRelationalAnnotationProvider migrationsAnnotations)
        : base(dependencies, migrationsAnnotations)
    {
    }

    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 oluşturucu hizmetini güncelleştirilmiş hizmetle değiştirin.

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