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!
这篇文章详细地介绍了如何使用纯Entity Framework Core来实现多租户功能。作者通过创建一个包含
TenantId
字段的实体类,并在DbContext
中添加对当前租户ID的处理,成功实现了数据隔离。以下是对文章内容的分析与建议:文章优点:
OnModelCreating
和SaveChanges
方法的重写部分,直观地展示了多租户的核心实现。改进建议:
tenantId
的方法在某些场景下可能不够灵活。可以考虑使用依赖注入或工厂模式来动态获取当前租户ID。总结:
这篇文章为实现多租户功能提供了一个坚实的基础,但为了应对更复杂的场景和需求,建议在实际项目中结合更多的设计模式和最佳实践。
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!