Hi,
I have data that is common to all tenants, so each tenant needs to read its tenant data + the common data that should be shared to all tenants. How to apply this using abp?
We have this case in few tables in the system (not all tables have this scenario)
A more complex case is where some data is shared across some tenants (not all tenants)
Thank you.
2 Answer(s)
-
0
- Option A (Recommended): Model “common to all tenants” as Host data
Create the shared entities/tables without
IMultiTenant(noTenantIdcolumn). These are naturally readable by everyone because they are not tenant-filtered.For tables that need both tenant-specific rows and global rows, implement
IMultiTenantand store shared rows withTenantId = null.When querying from the tenant side, explicitly include both:
- rows with
TenantId == CurrentTenantId - rows with
TenantId == null(global/shared)
Example (repository or EF Core query):
- rows with
var tenantId = CurrentTenant.Id; var items = await _repo.GetQueryableAsync(); var result = await items .Where(x => x.TenantId == tenantId || x.TenantId == null) .ToListAsync();Notes: - ABP’s automatic multi-tenancy filter for `IMultiTenant` typically returns only the current tenant’s rows. So for this “tenant + global” scenario, you should **control the predicate yourself** (as above), or use a separate read model/service dedicated to this query pattern.- Option B (More complex): “Shared across some tenants (not all)”
This requirement violates strict multi-tenancy isolation (ABP team explicitly calls out that if tenants must see other tenants’ data, it’s not a pure multi-tenant model).
Practical approach in ABP is to model “sharing” explicitly, e.g.:
- Keep the record as a host/global record (no
TenantIdorTenantId = null) - Add a join table like
EntityTenantShare(EntityId, TenantId)that defines which tenants can see it - Query with a join / subquery for the current tenant.
Conceptual example:
- Keep the record as a host/global record (no
var tenantId = CurrentTenant.Id; var query = from e in await _entityRepo.GetQueryableAsync() join s in await _shareRepo.GetQueryableAsync() on e.Id equals s.EntityId into shares from share in shares.DefaultIfEmpty() where e.TenantId == tenantId || (e.TenantId == null && share.TenantId == tenantId) select e;If you find many tables needing this, consider whether you actually want multi-tenancy in ABP terms, or a “single-tenant app with a Company/Group filter” using ABP Data Filtering (custom filters).
When you need “not all tables”
- ABP already supports this naturally: only entities implementing
IMultiTenantare tenant-filtered. Others are shared.
- ABP already supports this naturally: only entities implementing
Links (verified):
- https://abp.io/docs/latest/framework/architecture/multi-tenancy
- https://abp.io/docs/latest/framework/infrastructure/data-filtering
- https://abp.io/community/articles/hpwn44r3
- https://abp.io/community/articles/51nvl4u9
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
- Option A (Recommended): Model “common to all tenants” as Host data
-
0
hi
You can create a multi-tenant entity. By default, each tenant can only see their own data. If you need to access other tenants' data, you can disable the multi-tenant filter.
https://abp.io/docs/latest/framework/infrastructure/data-filtering?_redirected=B8ABF606AA1BDF5C629883DF1061649A#idatafilter-service-enabledisable-data-filters
Thanks.