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 TenantIdGenel 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 JOINSahip 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 CustomerIdDeğ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/OwnsManysahip olunan ilişkileri yapılandırır; ayırmak içinToTable()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
- Hevesli, Tembel ve Açık Yükleme
- Ham SQL, Saklı Yordamlar ve Enterpolasyon
- Derlenmiş Sorgular ve Performans
- Genel Sorgu Filtreleri ve Sahipli Varlıklar