<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg" -->

---
title: Multitenancy with .NET and EF Core: A Deep Dive (.NET 10)
description: A step-by-step tutorial on implementing multitenancy in a .NET 10 Web API using Entity Framework Core with the shared schema and global query filter strategy....
canonical: https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Multitenancy with .NET and EF Core: A Deep Dive (.NET 10) | daily.dev
og:description: A step-by-step tutorial on implementing multitenancy in a .NET 10 Web API using Entity Framework Core with the shared schema and global query filter strategy....
og:url: https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg
og:image: https://api.daily.dev/og/posts/7IhkHI9Mg.png
og:image:alt: Multitenancy with .NET and EF Core: A Deep Dive (.NET 10)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Multitenancy with .NET and EF Core: A Deep Dive (.NET 10)

**[We Are .NET](https://daily.dev/sources/wearedotnet)** · 53 min read · 0 upvotes · 0 comments

## Summary

A step-by-step tutorial on implementing multitenancy in a .NET 10 Web API using Entity Framework Core with the shared schema and global query filter strategy. Covers creating a Tenant entity, building an invitation-based user registration flow, auto-assigning TenantId via SaveChangesAsync override, and enforcing data isolation with EF Core global query filters. Also demonstrates per-user order filtering and an admin bypass using IgnoreQueryFilters. Three isolation strategies are compared: shared schema with global filters, schema-per-tenant, and database-per-tenant.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.youtube.com/watch?v=nhiWAeqlF9A>

## Questions this post answers

### How do I implement multi-tenant data isolation in EF Core using a shared database schema?

Add a tenant ID foreign key column to each tenant-scoped entity, then configure an EF Core global query filter (HasQueryFilter) that compares the entity's tenant ID to the current tenant ID resolved from a scoped service reading the JWT claim. This filters every LINQ query automatically without needing manual WHERE clauses, though raw SQL or Dapper calls can still bypass it and leak data.

_Anyone shipping tenant isolation in EF Core can compare approaches and gotchas on daily.dev._

### How can I automatically assign the tenant ID and creator user ID when saving new entities in EF Core?

Create marker interfaces like ITenant (with a TenantId property) and ICreatedByUser (with a CreatedByUserId property), implement them on relevant entities, then override SaveChangesAsync in the DbContext to loop through ChangeTracker entries in the Added state and assign the values from scoped ICurrentTenantService and ICurrentUserService instances resolved from JWT claims.

_Developers wiring up tenant-aware auditing logic can track EF Core patterns like this on daily.dev._

### Why is my ASP.NET Core JWT sub claim returning null when reading it with ClaimTypes lookups?

By default, ASP.NET Core's JWT bearer authentication maps inbound claims, converting the sub claim to the ClaimTypes.NameIdentifier value, so looking up sub directly returns null. Setting MapInboundClaims to false in the JWT bearer configuration preserves the original claim name so it matches what was issued in the token service.

_Developers debugging JWT claim mismatches can find fixes like this on daily.dev._

## Similar posts on daily.dev

- [Multi-Tenant Best Practices Can Backfire](https://daily.dev/posts/multi-tenant-best-practices-can-backfire-fjwau1jba) · CodeOpinion · 79 upvotes · 6 comments
- [ABP vs Clean Architecture templates, starter kits, and DIY ASP.NET Core](https://daily.dev/posts/abp-vs-clean-architecture-templates-starter-kits-and-diy-asp-net-core-fsvpolamr) · We Are .NET · 0 upvotes · 0 comments
- [Global Query Filters in EF Core](https://daily.dev/posts/global-query-filters-in-ef-core-cwq8yucpe) · Waseem .NET Newsletter · 1 upvotes · 0 comments

---

Tags: [#.net](https://daily.dev/tags/.net), [#jwt](https://daily.dev/tags/jwt)

[View this post on daily.dev](https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Multitenancy with .NET and EF Core: A Deep Dive (.NET 10)","url":"https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg"},"datePublished":"2026-08-11T08:12:12.326Z","dateModified":"2026-09-14T07:06:17.166Z","description":"A step-by-step tutorial on implementing multitenancy in a .NET 10 Web API using Entity Framework Core with the shared schema and global query filter strategy....","image":"https://i.ytimg.com/vi/nhiWAeqlF9A/sddefault.jpg","thumbnailUrl":"https://i.ytimg.com/vi/nhiWAeqlF9A/sddefault.jpg","isAccessibleForFree":true,"articleSection":"We Are .NET","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"We Are .NET","logo":"https://media.daily.dev/image/upload/s--BsnVOa3i--/f_auto/v1718347410/logos/wearedotnet","url":"https://daily.dev/sources/wearedotnet"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":".net,jwt","timeRequired":"PT53M","video":{"@type":"VideoObject","name":"Multitenancy with .NET and EF Core: A Deep Dive (.NET 10)","description":"A step-by-step tutorial on implementing multitenancy in a .NET 10 Web API using Entity Framework Core with the shared schema and global query filter strategy....","thumbnailUrl":"https://i.ytimg.com/vi/nhiWAeqlF9A/sddefault.jpg","uploadDate":"2026-08-11T08:12:12.326Z","duration":"PT53M","url":"https://api.daily.dev/r/7IhkHI9Mg","embedUrl":"https://www.youtube.com/embed/nhiWAeqlF9A"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"We Are .NET","item":"https://daily.dev/sources/wearedotnet"},{"@type":"ListItem","position":3,"name":"Multitenancy with .NET and EF Core: A Deep Dive (.NET 10)"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/multitenancy-with-net-and-ef-core-a-deep-dive-net-10--7ihkhi9mg#faq","mainEntity":[{"@type":"Question","name":"How do I implement multi-tenant data isolation in EF Core using a shared database schema?","acceptedAnswer":{"@type":"Answer","text":"Add a tenant ID foreign key column to each tenant-scoped entity, then configure an EF Core global query filter (HasQueryFilter) that compares the entity's tenant ID to the current tenant ID resolved from a scoped service reading the JWT claim. This filters every LINQ query automatically without needing manual WHERE clauses, though raw SQL or Dapper calls can still bypass it and leak data. Anyone shipping tenant isolation in EF Core can compare approaches and gotchas on daily.dev."}},{"@type":"Question","name":"How can I automatically assign the tenant ID and creator user ID when saving new entities in EF Core?","acceptedAnswer":{"@type":"Answer","text":"Create marker interfaces like ITenant (with a TenantId property) and ICreatedByUser (with a CreatedByUserId property), implement them on relevant entities, then override SaveChangesAsync in the DbContext to loop through ChangeTracker entries in the Added state and assign the values from scoped ICurrentTenantService and ICurrentUserService instances resolved from JWT claims. Developers wiring up tenant-aware auditing logic can track EF Core patterns like this on daily.dev."}},{"@type":"Question","name":"Why is my ASP.NET Core JWT sub claim returning null when reading it with ClaimTypes lookups?","acceptedAnswer":{"@type":"Answer","text":"By default, ASP.NET Core's JWT bearer authentication maps inbound claims, converting the sub claim to the ClaimTypes.NameIdentifier value, so looking up sub directly returns null. Setting MapInboundClaims to false in the JWT bearer configuration preserves the original claim name so it matches what was issued in the token service. Developers debugging JWT claim mismatches can find fixes like this on daily.dev."}}]}
```

