Skip to content

Entity Framework - Interceptors

Giriş

Entity Framework'te Interceptors (Kesiciler), veritabanı işlemleri sırasında belirli noktalarda müdahale etmeyi sağlayan güçlü bir özelliktir. Mid-level geliştiriciler için bu özelliğin anlaşılması ve etkin kullanımı önemlidir.

Interceptors'ın Önemi

  1. Esneklik
  2. İşlem öncesi/sonrası müdahale
  3. Özel iş mantığı ekleme
  4. Davranış değiştirme
  5. Genişletilebilirlik

  6. Güvenlik

  7. Veri doğrulama
  8. Yetkilendirme
  9. Audit logging
  10. Güvenlik kontrolleri

  11. Bakım

  12. Merkezi kontrol
  13. Kod tekrarını önleme
  14. Kolay test edilebilirlik
  15. Modüler yapı

Interceptor Tipleri

  1. Command Interceptor

    public class CustomCommandInterceptor : DbCommandInterceptor
    {
        public override InterceptionResult<DbDataReader> ReaderExecuting(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<DbDataReader> result)
        {
            // Command öncesi işlemler
            LogCommand(command);
            return result;
        }
    
        public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<DbDataReader> result,
            CancellationToken cancellationToken = default)
        {
            // Async command öncesi işlemler
            LogCommand(command);
            return new ValueTask<InterceptionResult<DbDataReader>>(result);
        }
    }
    

  2. Connection Interceptor

    public class CustomConnectionInterceptor : DbConnectionInterceptor
    {
        public override InterceptionResult ConnectionOpening(
            DbConnection connection,
            ConnectionEventData eventData,
            InterceptionResult result)
        {
            // Connection öncesi işlemler
            LogConnection(connection);
            return result;
        }
    
        public override ValueTask<InterceptionResult> ConnectionOpeningAsync(
            DbConnection connection,
            ConnectionEventData eventData,
            InterceptionResult result,
            CancellationToken cancellationToken = default)
        {
            // Async connection öncesi işlemler
            LogConnection(connection);
            return new ValueTask<InterceptionResult>(result);
        }
    }
    

  3. Transaction Interceptor

    public class CustomTransactionInterceptor : DbTransactionInterceptor
    {
        public override InterceptionResult TransactionStarting(
            DbConnection connection,
            TransactionStartingEventData eventData,
            InterceptionResult result)
        {
            // Transaction başlangıcı işlemleri
            LogTransactionStart();
            return result;
        }
    
        public override ValueTask<InterceptionResult> TransactionStartingAsync(
            DbConnection connection,
            TransactionStartingEventData eventData,
            InterceptionResult result,
            CancellationToken cancellationToken = default)
        {
            // Async transaction başlangıcı işlemleri
            LogTransactionStart();
            return new ValueTask<InterceptionResult>(result);
        }
    }
    

  4. SaveChanges Interceptor

    public class CustomSaveChangesInterceptor : SaveChangesInterceptor
    {
        public override InterceptionResult<int> SavingChanges(
            DbContextEventData eventData,
            InterceptionResult<int> result)
        {
            // SaveChanges öncesi işlemler
            ValidateChanges(eventData.Context);
            return result;
        }
    
        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(
            DbContextEventData eventData,
            InterceptionResult<int> result,
            CancellationToken cancellationToken = default)
        {
            // Async SaveChanges öncesi işlemler
            ValidateChanges(eventData.Context);
            return new ValueTask<InterceptionResult<int>>(result);
        }
    }
    

Interceptor Kullanımı

  1. DbContext Konfigürasyonu

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .AddInterceptors(new CustomCommandInterceptor())
            .AddInterceptors(new CustomConnectionInterceptor())
            .AddInterceptors(new CustomTransactionInterceptor())
            .AddInterceptors(new CustomSaveChangesInterceptor());
    }
    

  2. Dependency Injection ile Kullanım

    services.AddDbContext<ApplicationDbContext>(options =>
    {
        options
            .AddInterceptors(new CustomCommandInterceptor())
            .AddInterceptors(new CustomConnectionInterceptor())
            .AddInterceptors(new CustomTransactionInterceptor())
            .AddInterceptors(new CustomSaveChangesInterceptor());
    });
    

  3. Özel Interceptor Örnekleri

    // Audit Logging Interceptor
    public class AuditLoggingInterceptor : SaveChangesInterceptor
    {
        public override InterceptionResult<int> SavingChanges(
            DbContextEventData eventData,
            InterceptionResult<int> result)
        {
            var entries = eventData.Context.ChangeTracker.Entries();
            foreach (var entry in entries)
            {
                if (entry.State == EntityState.Added || 
                    entry.State == EntityState.Modified || 
                    entry.State == EntityState.Deleted)
                {
                    LogAudit(entry);
                }
            }
            return result;
        }
    }
    
    // Soft Delete Interceptor
    public class SoftDeleteInterceptor : SaveChangesInterceptor
    {
        public override InterceptionResult<int> SavingChanges(
            DbContextEventData eventData,
            InterceptionResult<int> result)
        {
            var entries = eventData.Context.ChangeTracker.Entries()
                .Where(e => e.State == EntityState.Deleted);
    
            foreach (var entry in entries)
            {
                if (entry.Entity is ISoftDelete softDelete)
                {
                    softDelete.IsDeleted = true;
                    entry.State = EntityState.Modified;
                }
            }
            return result;
        }
    }
    

Best Practices

  1. Interceptor Tasarımı
  2. Single Responsibility
  3. Dependency Injection
  4. Error handling
  5. Performance

  6. Güvenlik

  7. Input validation
  8. Authorization
  9. Audit logging
  10. Security checks

  11. Performans

  12. Minimal müdahale
  13. Async operations
  14. Resource yönetimi
  15. Caching

  16. Bakım

  17. Kod organizasyonu
  18. Documentation
  19. Testing
  20. Monitoring

Mülakat Soruları

Temel Sorular

  1. Entity Framework'te Interceptor nedir?
  2. Cevap: Interceptor, veritabanı işlemleri sırasında belirli noktalarda müdahale etmeyi sağlayan bir özelliktir.

  3. Entity Framework'te kaç çeşit Interceptor vardır?

  4. Cevap: Command Interceptor, Connection Interceptor, Transaction Interceptor ve SaveChanges Interceptor.

  5. Entity Framework'te Interceptor nasıl kaydedilir?

  6. Cevap: DbContext.OnConfiguring metodunda veya Dependency Injection ile AddInterceptors metodu kullanılarak.

  7. Entity Framework'te Interceptor ne zaman kullanılır?

  8. Cevap: Audit logging, soft delete, validation, authorization gibi cross-cutting concerns'ler için kullanılır.

  9. Entity Framework'te Interceptor performansı nasıl etkiler?

  10. Cevap: Her işlem için ek yük getirir, bu nedenle dikkatli kullanılmalıdır.

Teknik Sorular

  1. Command Interceptor nasıl oluşturulur?
  2. Cevap:

    public class CustomCommandInterceptor : DbCommandInterceptor
    {
        public override InterceptionResult<DbDataReader> ReaderExecuting(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<DbDataReader> result)
        {
            LogCommand(command);
            return result;
        }
    }
    

  3. SaveChanges Interceptor nasıl oluşturulur?

  4. Cevap:

    public class CustomSaveChangesInterceptor : SaveChangesInterceptor
    {
        public override InterceptionResult<int> SavingChanges(
            DbContextEventData eventData,
            InterceptionResult<int> result)
        {
            ValidateChanges(eventData.Context);
            return result;
        }
    }
    

  5. Soft Delete Interceptor nasıl oluşturulur?

  6. Cevap:

    public class SoftDeleteInterceptor : SaveChangesInterceptor
    {
        public override InterceptionResult<int> SavingChanges(
            DbContextEventData eventData,
            InterceptionResult<int> result)
        {
            var entries = eventData.Context.ChangeTracker.Entries()
                .Where(e => e.State == EntityState.Deleted);
    
            foreach (var entry in entries)
            {
                if (entry.Entity is ISoftDelete softDelete)
                {
                    softDelete.IsDeleted = true;
                    entry.State = EntityState.Modified;
                }
            }
            return result;
        }
    }
    

  7. Audit Logging Interceptor nasıl oluşturulur?

  8. Cevap:

    public class AuditLoggingInterceptor : SaveChangesInterceptor
    {
        public override InterceptionResult<int> SavingChanges(
            DbContextEventData eventData,
            InterceptionResult<int> result)
        {
            var entries = eventData.Context.ChangeTracker.Entries();
            foreach (var entry in entries)
            {
                if (entry.State == EntityState.Added || 
                    entry.State == EntityState.Modified || 
                    entry.State == EntityState.Deleted)
                {
                    LogAudit(entry);
                }
            }
            return result;
        }
    }
    

  9. Interceptor'lar nasıl test edilir?

  10. Cevap:
    [Test]
    public void TestCommandInterceptor()
    {
        var interceptor = new CustomCommandInterceptor();
        var command = new Mock<DbCommand>();
        var eventData = new CommandEventData(null, null, null);
        var result = new InterceptionResult<DbDataReader>();
    
        var actual = interceptor.ReaderExecuting(command.Object, eventData, result);
        Assert.That(actual, Is.EqualTo(result));
    }
    

İleri Seviye Sorular

  1. Entity Framework'te Interceptor performansı nasıl optimize edilir?
  2. Cevap:

    • Minimal müdahale
    • Async operations
    • Resource yönetimi
    • Caching stratejileri
    • Conditional execution
  3. Entity Framework'te distributed sistemlerde Interceptor nasıl yönetilir?

  4. Cevap:

    • Distributed transactions
    • Event sourcing
    • Message queues
    • Consistency
    • Conflict resolution
  5. Entity Framework'te high concurrency senaryolarında Interceptor nasıl yönetilir?

  6. Cevap:

    • Optimistic concurrency
    • Pessimistic concurrency
    • Retry mekanizmaları
    • Queue yönetimi
    • Batch processing
  7. Entity Framework'te Interceptor monitoring ve profiling nasıl yapılır?

  8. Cevap:

    • Performance metrics
    • Resource monitoring
    • Profiling tools
    • Health checks
    • Logging
  9. Entity Framework'te custom Interceptor stratejileri nasıl geliştirilir?

  10. Cevap:
    • Custom event handling
    • Custom validation
    • Custom logging
    • Custom monitoring
    • Custom optimization