Part of DKNet.EfCore.DataAuthorization. In the Quick Start, IDataOwnerDbContext.AccessibleKeys forwards the provider keys. Override the provider to grant several keys:
public sealed class DemoOwner : IDataOwnerProvider
{
public string? GetOwnershipKey() => "tenant-a";
public ICollection<string> GetAccessibleKeys() => ["tenant-a", "tenant-b"];
}
The predicate is IsUnrestrictedAccess || AccessibleKeys.Contains(entity.OwnedBy). Empty keys deny every owned row unless unrestricted access is explicitly enabled. DataOwnerAuthQuery.IsIgnorable is false, so a specification’s IgnoreQueryFilters() does not bypass it.
| Setting | Type | Default | Effect |
|---|---|---|---|
AccessibleKeys |
IEnumerable<string> |
Required implementation | Keys allowed on reads. |
IsUnrestrictedAccess |
bool |
false |
Explicit context-wide read-filter bypass. |
GetAccessibleKeys() |
ICollection<string> |
One ownership key, or empty for null/empty key | Source your context can forward; also used by the save guard. |
AddDataOwnerProvider<TDbContext, TProvider>() requires TDbContext : DbContext, IDataOwnerDbContext. It registers a global model builder and scoped provider, then the keyed save hook. Call UseAutoConfigModel<TDbContext>() on options to apply the builder.
The ownership architecture shows the read and write paths; the audit-field split explains which provider fills identity fields. The filter is installed on hierarchy roots only, covering TPH, TPT and TPC descendants. A derived IOwnedBy type below a root that does not implement IOwnedBy throws during model building: move the contract to the root.
UseAutoConfigModel leaves the filter unapplied without an error. Check the complete registration, not just the provider.IDataOwnerDbContext, or model building throws.AccessibleKeys declared as IEnumerable<string>, matching the interface and the query translation path.IsUnrestrictedAccess changes reads, not the reassignment guard.OR branch can hinder owner-column index use, and varying key lists can change SQL and query plans. Measure your provider and workload; this package does not promise an index seek.