Multi-tenant requires many features because the data can be separated by different tenants. So when you are accessing the database, you don't need to worry that your operation will affect other tenants.
Multi-tenancy is the ASP.NET boilerplate's most important feature and works perfectly with Domain-driven design. But how can we implement the multitenant feature with only pure Entity Framework Core?
First, create an example entity like this:
public class Blog
{
public int Id { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
}
The Id of the blog will be your primary key in your database. And the TenantId
represents which tenant of this blog belongs to. So the table was grouped by TenantId
multiple collections of the Blog.
Create your DBContext
like this:
public class BloggingContext : DbContext
{
private readonly int _tenantId;
public BloggingContext(int tenantId)
{
_tenantId = tenantId;
}
public DbSet<Blog> Blogs { get; set; }
}
To configure your SQL Server connection, override the default OnConfiguring
like this:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Demo.QueryFilters;Trusted_Connection=True;ConnectRetryCount=0;");
}
When the developer is trying to select blogs from the DBContext
, we need to add a filter to get only blogs from the current tenant. Override the default OnModelCreating
method.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().HasQueryFilter(b => EF.Property<int>(b, "TenantId") == _tenantId);
}
If the developer is inserting an item to the table, we need to help him set the TenantId
.
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
foreach (var item in ChangeTracker.Entries().Where(e => e.State == EntityState.Added && e.Metadata.GetProperties().Any(p => p.Name == "TenantId")))
{
item.CurrentValues["TenantId"] = _tenantId;
}
return base.SaveChanges();
}
Now we have a multi-tenant DBContext. With a BloggingContext
, a developer can keep writing LINQ or lambda expression like he previously did and desn' need to concern about the tenant context for our context can work with that automatically.
But to get a BloggingContext
there is an additional step. You need to specify your tenant'id when constructing it.
int tenantId = 3;
var dbContext = new BloggingContext(tenantId);
And you can migrate an existing project using Entity Framework Core to the multi-tenant application easily!
I just read your blog post on implementing multi-tenancy in pure Entity Framework Core, and I must say that it is a well-written and informative piece. Your approach to handling multi-tenancy by adding a
TenantId
property to the entity and then modifying theDBContext
to filter the data based on the current tenant is quite innovative and practical.The step-by-step instructions you provided, along with the code snippets, make it easy for readers to understand and implement the concept in their projects. The fact that developers can continue to use LINQ or lambda expressions without worrying about tenant context is a significant advantage of your approach.
However, there are a few areas where the blog post could be improved. Firstly, it would be helpful to provide more background information on multi-tenancy and why it is essential in modern web applications. This would help readers who are new to the concept to grasp its importance better.
Secondly, while your approach is excellent for handling data access, it would be beneficial to discuss how to handle tenant-specific configurations, such as connection strings, in a multi-tenant application. This would give readers a more comprehensive understanding of implementing multi-tenancy in their projects.
Lastly, it would be interesting to explore how your approach can be extended to handle more complex scenarios, such as tenant-specific data validation or business rules. This would help readers understand the full potential of your solution and how it can be adapted to suit their specific needs.
Overall, I commend you for writing an insightful blog post on implementing multi-tenancy in Entity Framework Core. Your approach is both innovative and practical, making it an excellent resource for developers looking to implement multi-tenancy in their applications. With a few minor improvements, this blog post can become an even more valuable resource for the developer community. Keep up the great work!