0Pricing
C# Academy · Ders

Genel Sorgu Filtreleri ve Sahipli Varlıklar

Genel sorgu filtreleriyle kiracıları birbirinden ayırın ve yumuşak silme uygulayın; sahipli varlık türleriyle değer nesnelerini eşleyin.

Genel Sorgu Filtreleri ve Sahipli Varlıklar, CoddyKit'te ücretsiz bir C# Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C# Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C# Academy kursu toplamda 4 dersten oluşur.

Genel Sorgu Filtreleri Nedir?

Genel sorgu filtreleri, belirli bir varlık türü için her LINQ sorgusuna otomatik olarak uygulanan WHERE koşullarıdır. Yumuşak silme, çok kiracılı kullanım ve satır düzeyinde güvenlik için idealdir — koşulu her yerde tekrarlamanıza gerek kalmaz.

Genel Filtreyle Yumuşak Silme

Bir IsDeleted bayrağı ekleyin ve silinen kayıtların, filtreyi açıkça yok saymadığınız sürece hiçbir zaman döndürülmemesi için genel bir filtre yapılandırın.

// Entity with soft-delete flag
public class Post
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public bool IsDeleted { get; set; }
}

// Configure in OnModelCreating
modelBuilder.Entity<Post>()
    .HasQueryFilter(p => !p.IsDeleted);

// All queries now implicitly add WHERE IsDeleted = 0:
var posts = await _db.Posts.ToListAsync();

Genel Filtreyle Çok Kiracılı Kullanım

Geçerli kiracıyı kapsamı belirlenmiş bir hizmetten okuyan bir filtre kullanın. Her sorgu otomatik olarak geçerli kiracının verileriyle sınırlandırılır.

public class AppDbContext : DbContext
{
    private readonly ICurrentUserService _user;

    public AppDbContext(DbContextOptions<AppDbContext> opt, ICurrentUserService user)
        : base(opt) => _user = user;

    protected override void OnModelCreating(ModelBuilder mb)
    {
        mb.Entity<Order>().HasQueryFilter(
            o => o.TenantId == _user.TenantId);
    }
}
// Every Order query automatically filters by TenantId

Genel Filtreleri Yok Sayma

Bazen filtreyi devre dışı bırakmanız gerekir — örneğin tüm kiracılar için yönetici sorgularında veya yumuşak olarak silinmiş bir kaydı geri yüklerken. Yalnızca ilgili sorgu için IgnoreQueryFilters() kullanın.

// Admin: see ALL posts including deleted
var allPosts = await _db.Posts
    .IgnoreQueryFilters()
    .ToListAsync();

// Restore a specific deleted post
var deleted = await _db.Posts
    .IgnoreQueryFilters()
    .FirstOrDefaultAsync(p => p.Id == 42);

if (deleted is not null)
{
    deleted.IsDeleted = false;
    await _db.SaveChangesAsync();
}

Gezinme Özelliklerinde Filtreler

Genel filtreler birleştirmelerde de etkili olur. Posts için bir filtre varsa, Include aracılığıyla yüklenen ilişkili Posts da otomatik olarak filtrelenir.

// Blog with soft-delete filter on Posts
var blog = await _db.Blogs
    .Include(b => b.Posts) // only non-deleted posts are included
    .FirstOrDefaultAsync(b => b.Id == 1);

// blog.Posts contains only active posts — the filter applied in the JOIN

Sahip Olunan Varlık Türleri: Kavram

Sahip olunan varlık türleri, yalnızca tek bir sahip varlığa ait olan sınıflardır. Birincil anahtarları yoktur ve varsayılan olarak aynı tabloda depolanırlar. DDD'de değer nesneleri için idealdir.

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public Address BillingAddress  { get; set; } = new();
    public Address ShippingAddress { get; set; } = new();
}

public class Address
{
    public string Street  { get; set; } = "";
    public string City    { get; set; } = "";
    public string ZipCode { get; set; } = "";
    public string Country { get; set; } = "";
}

Sahip Olunan Varlıkları Yapılandırma

Tek bir sahip olunan varlığı yapılandırmak için OwnsOne kullanın. EF Core, sütun adlarının önüne varsayılan olarak gezinme özelliğinin adını ekler.

modelBuilder.Entity<Customer>(entity =>
{
    entity.OwnsOne(c => c.BillingAddress, addr =>
    {
        addr.Property(a => a.Street).HasMaxLength(300);
        addr.Property(a => a.Country).HasMaxLength(2);
    });

    entity.OwnsOne(c => c.ShippingAddress);
});
// Table: Customers with columns:
// BillingAddress_Street, BillingAddress_City, ...
// ShippingAddress_Street, ShippingAddress_City, ...

Sahip Olunan Varlıkları Ayrı Tabloda Depolama

Sahip olunan varlıkları kendi tablolarında depolamak için OwnsOne içinde ToTable() kullanın — bu, veriler büyük olduğunda veya isteğe bağlı olduğunda kullanışlıdır.

modelBuilder.Entity<Customer>().OwnsOne(
    c => c.BillingAddress,
    addr => addr.ToTable("CustomerBillingAddresses"));

// Now BillingAddress columns are in a separate table
// with a FK back to CustomerId

Değer Nesnesi Koleksiyonları için OwnsMany

OwnsMany, sahip olunan varlıklardan oluşan bir koleksiyonu yapılandırır — örneğin, alt tabloda depolanan e-posta adresleri veya telefon numaraları listesi.

public class Customer
{
    public int Id { get; set; }
    public IList<PhoneNumber> PhoneNumbers { get; set; } = new List<PhoneNumber>();
}

public class PhoneNumber
{
    public string Number { get; set; } = "";
    public string Type   { get; set; } = "";
}

modelBuilder.Entity<Customer>()
    .OwnsMany(c => c.PhoneNumbers,
        phone => phone.ToTable("CustomerPhones"));

Hiyerarşi Başına Tablo ve Sahip Olunan Varlıklar

Genel filtreler, alt türleri birbirinden ayıran bir ayrıştırıcı sütunun bulunduğu TPH (Hiyerarşi Başına Tablo) kalıtımıyla da iyi çalışır. Türe özgü sorgular için ayrıştırıcıya dayalı bir filtre uygulayın.

// Base entity
public abstract class Payment { public int Id { get; set; } }
public class CardPayment  : Payment { public string CardLast4 { get; set; } = ""; }
public class BankPayment  : Payment { public string IBAN { get; set; } = ""; }

// All Payment subtypes in one table with a Discriminator column
// No extra config needed — EF Core handles TPH by default
var cards = await _db.Set<CardPayment>().ToListAsync();
// SQL: SELECT * FROM Payments WHERE Discriminator = 'CardPayment'

Gerçek Dünya: SaaS Kiracılarını Yalıtma

Eksiksiz bir SaaS çok kiracılı kullanım kurulumu, genel sorgu filtrelerini kapsamı belirlenmiş bir kiracı bağlamıyla birleştirir. Böylece sorguya özel herhangi bir kod yazmadan her sorgu otomatik olarak doğru kapsamla sınırlandırılır.

// Scoped tenant service
public class TenantContext
{
    public Guid TenantId { get; set; }
}

// DbContext uses it
modelBuilder.Entity<Invoice>().HasQueryFilter(
    inv => inv.TenantId == _tenantCtx.TenantId);
modelBuilder.Entity<Customer>().HasQueryFilter(
    c => c.TenantId == _tenantCtx.TenantId);

// Queries are automatically scoped:
var invoices = await _db.Invoices.ToListAsync();
// WHERE TenantId = 'current-tenant-guid'

Hızlı Kontrol

Belirli bir sorgu için genel sorgu filtresini geçici olarak devre dışı bırakmak üzere hangi yöntemi çağırırsınız?

Özet: Genel Filtreler ve Sahip Olunan Varlıklar

Temel çıkarımlar:

  • Genel sorgu filtreleri, bir varlık için her sorguya otomatik olarak WHERE koşulları ekler
  • Yumuşak silme, çok kiracılı kullanım ve satır düzeyinde güvenlik için idealdir
  • Yönetim veya geri yükleme işlemleri için IgnoreQueryFilters() ile devre dışı bırakılabilir
  • Sahip olunan varlıklar değer nesnelerini modeller — PK yoktur, sahibin tablosunda depolanır
  • OwnsOne / OwnsMany sahip olunan ilişkileri yapılandırır; ayırmak için ToTable() kullanın

Sıkça Sorulan Sorular

“Genel Sorgu Filtreleri ve Sahipli Varlıklar” dersi ücretsiz mi?

Evet — “Genel Sorgu Filtreleri ve Sahipli Varlıklar” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C# Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C# Academy kursu toplamda 4 dersten oluşur.

“Genel Sorgu Filtreleri ve Sahipli Varlıklar” dersinde ne öğreneceğim?

Genel sorgu filtreleriyle kiracıları birbirinden ayırın ve yumuşak silme uygulayın; sahipli varlık türleriyle değer nesnelerini eşleyin. C# Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

C# Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te C# Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.

“Genel Sorgu Filtreleri ve Sahipli Varlıklar” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu C# Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her C# Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Hevesli, Tembel ve Açık Yükleme
  2. Ham SQL, Saklı Yordamlar ve Enterpolasyon
  3. Derlenmiş Sorgular ve Performans
  4. Genel Sorgu Filtreleri ve Sahipli Varlıklar
← C# Academy Sayfasına Dön