Skip to main content
BuildingBlocks.Specification, Ardalis.Specification 9.x üzerine kurulu ince bir katmandır. Sorgu mantığını (where/include/orderby/paging) repository’den ayrı, test edilebilir ve cache’lenebilir spec sınıflarına taşır. İki ek değer sunar: in-memory mantıksal kombinatörler (And/Or/Not) ve spec’e doğrudan cache tag/TTL iliştirme.
Repository altyapısı (EFRepository, CachedRepository, ListAsync) ve hibrit cache davranışı için bkz. Veri Katmanı ve Cache.

CompositeSpecification<T>

Spec’lerin türetildiği temel sınıf. Ardalis.Specification.Specification<T>’i genişletir ve in-memory değerlendirme için IInMemorySpecification<T> sağlar.
public abstract class CompositeSpecification<T>
    : Ardalis.Specification.Specification<T>, IInMemorySpecification<T>
{
    public abstract override bool IsSatisfiedBy(T candidate);

    public IInMemorySpecification<T> And(IInMemorySpecification<T> other);
    public IInMemorySpecification<T> AndNot(IInMemorySpecification<T> other);
    public IInMemorySpecification<T> Or(IInMemorySpecification<T> other);
    public IInMemorySpecification<T> OrNot(IInMemorySpecification<T> other);
    public IInMemorySpecification<T> Not();
}
ÜyeAmaç
IsSatisfiedBy(T)Bir adayın (DB’ye gitmeden) spec’i karşılayıp karşılamadığını döner
And / AndNot / Or / OrNot / Notİki spec’i in-memory mantıksal olarak birleştirir (AndSpecification<T> vb. döndürür)
Query.* zinciri (Where, Include, OrderBy, Skip, Take) Ardalis’ten gelir ve EF Core’a çevrilir; IsSatisfiedBy ise aynı kuralı bellekte de uygulanabilir kılar.

Filtreler — IFilter / FilterBase

API’den gelen liste/arama parametrelerini standartlaştıran kontrat. FilterBase türetilerek aggregate’e özel filtre yapılır.
ÜyeTipAçıklama
HasTenantboolTenantId.HasValue
IsPagingEnabledboolPageSize > 0 && Page >= 0
HasSearch / HasSortboolSearchTerm / SortBy dolu mu
Page / PageSizeintSayfalama (0-based — bkz. uyarı)
Skip / TakeintPaginationHelper.CalculateSkip/Take’ten hesaplanır
TenantIdGuid?Multi-tenant filtre
OrderBystring"asc" / "desc"OrderByASC/OrderByDESC türetilir
SortBystringSıralanacak alan adı
SearchTermstringArama; IsSearchTermNumeric/IsSearchTermTckn/IsSearchTermDateTime yardımcıları
Sayfalama 0-based’tir: IsPagingEnabled koşulu Page >= 0 ister ve PaginationHelper 0’ıncı sayfayı ilk sayfa kabul eder. Frontend useState(0) ile başlamalı; page=1 göndermek ilk sayfayı sessizce atlar.

Cache entegrasyonu

Cache, Ardalis’in mevcut Query.EnableCache(name, args) zinciriyle açılır. Paket buna iki fluent uzantı ekler:
UzantıEtki
WithTags(params string[])Spec’e invalidation tag’leri iliştirir (SetCacheTags) — CachedRepository bunları HybridCache.GetOrCreateAsync’e geçirir
WithCacheTtl(TimeSpan)Spec’e per-entry TTL iliştirir (SetCacheTTL) — HybridCacheEntryOptions.Expiration’a yansır
Ad bilerek WithCacheTtl’dir — Ardalis’in WithTimeToLive’i ile ambiguous reference olmasın diye. Aynı şekilde paralel ICacheSpecificationBuilder<T> kaldırılmıştır; Ardalis.Specification.ICacheSpecificationBuilder<T> kullanılır.

Kullanım — spec tanımı + Repository.ListAsync

public sealed class GetActiveFaqsSpecification : CompositeSpecification<Faq>
{
    public GetActiveFaqsSpecification(Guid? tenantId)
    {
        Query
            .Where(f => f.IsActive)
            .OrderBy(f => f.Order)
            .EnableCache(nameof(GetActiveFaqsSpecification), tenantId ?? Guid.Empty)
            .WithCacheTtl(TimeSpan.FromMinutes(10))
            .WithTags("faq", $"tenant:{tenantId}");
    }

    // In-memory değerlendirme (ör. domain event sonrası filtre)
    public override bool IsSatisfiedBy(Faq candidate) => candidate.IsActive;
}
// Read repository (CachedRepository decorator) ile — sonuç cache'lenir
var spec = new GetActiveFaqsSpecification(tenantId);
IReadOnlyList<Faq> faqs = await _readRepository.ListAsync(spec, ct);

// Aggregate değiştiğinde aynı tag düşürülür (domain event handler içinde)
await _cache.RemoveByTagAsync("faq", ct);
// In-memory kombinasyon — DB'ye gitmeden iki kuralı birleştir
IInMemorySpecification<User> activeAndVerified =
    new ActiveUserSpec().And(new PhoneVerifiedSpec());

bool ok = ((CompositeSpecification<User>)activeAndVerified).IsSatisfiedBy(user);

İlgili

Veri katmanı

EFRepository, CachedRepository ve SpecificationEvaluator.

Cache

EnableCache/WithTags ile hibrit cache entegrasyonu.

Domain

Spec’lerin aggregate başına organizasyonu.

Invalidation

Tag-based eviction ve domain event tetikleme.