NetCoreBackend.NArchitecture.Core.Persistence
1.1.1
dotnet add package NetCoreBackend.NArchitecture.Core.Persistence --version 1.1.1
NuGet\Install-Package NetCoreBackend.NArchitecture.Core.Persistence -Version 1.1.1
<PackageReference Include="NetCoreBackend.NArchitecture.Core.Persistence" Version="1.1.1" />
<PackageVersion Include="NetCoreBackend.NArchitecture.Core.Persistence" Version="1.1.1" />
<PackageReference Include="NetCoreBackend.NArchitecture.Core.Persistence" />
paket add NetCoreBackend.NArchitecture.Core.Persistence --version 1.1.1
#r "nuget: NetCoreBackend.NArchitecture.Core.Persistence, 1.1.1"
#:package NetCoreBackend.NArchitecture.Core.Persistence@1.1.1
#addin nuget:?package=NetCoreBackend.NArchitecture.Core.Persistence&version=1.1.1
#tool nuget:?package=NetCoreBackend.NArchitecture.Core.Persistence&version=1.1.1
Core.Persistence
EF Core tabanlı repository pattern implementasyonu. Soft delete, sayfalama, dinamik filtreleme ve multi-tenant entity desteği içerir.
Entity Hiyerarşisi
Entity<TId> ← Id, CreatedDate, UpdatedDate, DeletedDate
└── TenantEntity<TId> ← + TenantId (Guid) — tenant-aware entity'ler için
Repository Pattern
// Tenant-aware entity için: tenantSetter ZORUNLU.
// AddMultiTenancy() çağrılmamışsa ITenantEntity Add'inde hard error fırlar.
public class OrderRepository : EfRepositoryBase<Order, Guid, AppDbContext>
{
public OrderRepository(AppDbContext context, ITenantEntitySetter tenantSetter)
: base(context, tenantSetter) { }
}
// Tenant-bağımsız entity için (Country gibi): tenantSetter null geçilebilir.
public class CountryRepository : EfRepositoryBase<Country, int, AppDbContext>
{
public CountryRepository(AppDbContext context)
: base(context, tenantSetter: null) { }
}
// Async interface
IAsyncRepository<Product, Guid>
// Sync interface
IRepository<Product, Guid>
Özellikler
| Özellik | Açıklama |
|---|---|
| Soft Delete | DeletedDate set edilerek soft silinir. Global query filter ile filtrelenir. Cascade soft-delete tenant-aware (başka tenant'ın row'una dokunulmaz). withDeleted: true silinmiş kayıtları getirir ancak tenant izolasyonunu korur — başka tenant'ın verisi görünmez. |
| Sayfalama | ToPaginateAsync(index, size, from) — IPaginate<T> döner. size <= 0 veya from > index ArgumentOutOfRangeException fırlatır. |
| Dinamik Filtreleme | GetListByDynamicAsync(DynamicQuery) — field, operator, value, logic desteği. [NotFilterable] ile işaretli property'ler reddedilir. |
| Tenant Otomatik Set | Add/AddRange'de ITenantEntity ise TenantId otomatik set edilir; ITenantEntitySetter register edilmemişse hard error. |
| SQL Komutları | ExecuteSqlRawAsync, ExecuteStoredProcedureAsync, ExecuteSqlCommand<TResult> |
NotFilterable — Hassas property'leri whitelist'ten çıkar
Dinamik query'de kullanıcı-sağlı field ismi typeof(TEntity) üzerinde public property arar. Hassas alanlara (parola hash'i, internal audit field) erişimi blocklamak için [NotFilterable] attribute'unu kullan:
public class User : TenantEntity<Guid>
{
public string Email { get; set; }
[NotFilterable] public byte[] PasswordHash { get; set; }
[NotFilterable] public byte[] PasswordSalt { get; set; }
}
User ve PlatformAdmin framework içinde halihazırda işaretlidir.
Tenant Entity Oluşturma
// Tenant-aware entity
public class Order : TenantEntity<Guid>
{
public decimal Total { get; set; }
}
// Normal (cross-tenant) entity
public class Country : Entity<int>
{
public string Name { get; set; }
}
SQL Metodları ve Tenant Güvenliği
ExecuteSqlCommand — Güvenli ✅
DbSet.FromSqlRaw() üzerinden çalışır. EF Core, yazdığın SQL'i subquery olarak sarar ve global query filter'ı otomatik uygular:
-- Yazdığın:
SELECT * FROM Orders WHERE Total > 100
-- EF Core'un ürettiği:
SELECT * FROM (...) AS t WHERE t.TenantId = 'acme-guid' AND t.DeletedDate IS NULL
ExecuteSqlRawAsync / ExecuteStoredProcedureAsync — Manuel Tenant Filtresi ⚠️
Database.ExecuteSqlRawAsync() doğrudan veritabanına gider, EF Core filtrelerini tamamen bypass eder. TenantEntity üzerinde çağrıldığında tenant context yoksa exception fırlatır (SuperAdmin hariç).
// Concrete repository içinde CurrentTenantId kullan:
public async Task<int> BulkArchiveAsync(DateTime before)
{
return await ExecuteSqlRawAsync(
"UPDATE Orders SET Archived = 1 WHERE TenantId = @p0 AND CreatedDate < @p1",
[CurrentTenantId, before] // ← CurrentTenantId protected property'den gelir
);
}
// Stored procedure: proc kendi içinde @tenantId parametresi almalı
public async Task<int> ArchiveOldOrdersAsync(DateTime before)
{
return await ExecuteStoredProcedureAsync(
"sp_ArchiveOldOrders(@p0, @p1)",
[CurrentTenantId, before]
);
}
CurrentTenantId → EfRepositoryBase'de protected Guid? CurrentTenantId => TenantSetter?.CurrentTenantId; olarak tanımlıdır.
ExecuteUpdateAsync / ExecuteDeleteAsync — Bulk operations, tenant-safe ✅
EF Core 7+ bulk update/delete API'sinin (UpdateSettersBuilder<T>) tenant-aware wrapper'ı. Predicate Query() üzerinden zincirlendiği için EF Core'un global query filter'ı otomatik uygulanır; ek olarak GuardTenantContext() raw-SQL path'leriyle aynı tenant context kontrolünü yapar.
// Bulk update — sadece current tenant'ın kayıtları etkilenir
await _orderRepo.ExecuteUpdateAsync(
predicate: o => o.Status == OrderStatus.Pending && o.CreatedDate < cutoff,
setPropertyCalls: setters => setters.SetProperty(o => o.Status, OrderStatus.Expired),
cancellationToken: ct);
// Bulk delete — soft-delete istiyorsan ExecuteUpdate ile DeletedDate yaz
await _orderRepo.ExecuteDeleteAsync(
predicate: o => o.Status == OrderStatus.Archived && o.UpdatedDate < cutoff,
cancellationToken: ct);
Update/Delete'in tek-row paterninden farkı: payload pre-load gerekmez, tek SQL statement gönderilir, bellek efficient. Kullanırken predicate'in TENANT scope'unda olduğundan emin ol — yanlış bir predicate bütün tenant'ın verisini etkileyebilir.
Dinamik Query
{
"filter": { "field": "name", "operator": "contains", "value": "phone" },
"sort": [{ "field": "createdDate", "dir": "desc" }]
}
Desteklenen operatörler: eq, neq, lt, lte, gt, gte, isnull, isnotnull, startswith, endswith, contains, doesnotcontain, in, between
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.EntityFrameworkCore (>= 10.0.5)
- Microsoft.EntityFrameworkCore.InMemory (>= 10.0.5)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.5)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Caching.Memory (>= 10.0.5)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.5)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- System.Linq.Dynamic.Core (>= 1.7.1)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on NetCoreBackend.NArchitecture.Core.Persistence:
| Package | Downloads |
|---|---|
|
NetCoreBackend.NArchitecture.Core.MultiTenancy
Multi-tenancy infrastructure: tenant resolution via JWT, header and subdomain, ITenantContext, TenantMiddleware and SuperAdmin impersonation support. |
|
|
NetCoreBackend.NArchitecture.Core.Security
Provides security utilities for hashing, encryption, JWT, authenticator, and more. |
|
|
NetCoreBackend.NArchitecture.Core.Persistence.DependencyInjection
Provides dependency injection extensions for NArchitecture.Core.Persistence. |
|
|
NetCoreBackend.NArchitecture.Core.Outbox
Transactional Outbox pattern — atomic DB-write + event publish with retry, poison-pill handling and background dispatch. |
|
|
NetCoreBackend.NArchitecture.Core.Persistence.WebApi
Provides utilities for integrating persistence services with ASP.NET Web API projects. |
GitHub repositories
This package is not used by any popular GitHub repositories.