多租户访问控制:存储库或服务层?

Pet*_*ron 10 asp.net-mvc access-control repository-pattern multi-tenant

在基于Rob Conery的MVC Storefront的多租户ASP.NET MVC应用程序中,我应该在存储库服务层中过滤租户的数据吗?

1.在存储库中过滤租户的数据:

public interface IJobRepository
{
    IQueryable<Job> GetJobs(short tenantId);
}
Run Code Online (Sandbox Code Playgroud)

2.让服务按租户过滤存储库数据:

public interface IJobService
{
    IList<Job> GetJobs(short tenantId);
}
Run Code Online (Sandbox Code Playgroud)

我的直觉是在服务层(选项2)中做到这一点,但可以说每个租户本质上应该有自己的"虚拟存储库"(选项1),其中这个责任在于存储库.

  • 哪种方法最优雅:选项1,选项2还是有更好的方法吗?

更新:

我尝试了在存储库中提出过滤的提议,但问题是我的应用程序提供了租户上下文(通过子域)并且只与服务层交互.将上下文一直传递到存储库层是一项任务.

所以我选择在服务层过滤我的数据.我觉得存储库应该代表存储库中物理上可用的所有数据,并使用适当的过滤器来检索服务层使用的特定于租户的数据.

最后更新:

由于不必要的复杂性,我最终放弃了这种方法.请参阅下面的答案.

uvi*_*ita 5

@FreshCode,我们在存储库中执行,并且我们不将租户作为参数传递.我们使用以下方法:

public IQueryable<Job> GetJobs()
{
    return _db.Jobs.Where(j=>j.TenantId == Context.TenantId);
}
Run Code Online (Sandbox Code Playgroud)

上下文是存储库具有的依赖关系,它是在BeginRequest中创建的,您可以根据该URL确定租户.我认为通过这种方式它非常透明,你可以避免tenantId参数,这可能会有点令人不安.

问候.


Pet*_*ron 3

更新:不采用多租户方法让我损失了数百小时的技术债务。四年后,我希望我能花时间首先实施清洁租户方法。不要犯同样的错误!


旧的、过时的答案:

我最终删除了所有多租户代码,转而为每个租户使用单独的应用程序和数据库。就我而言,我几乎没有不经常更换的租户,所以我可以这样做。

我所有的控制器、会员提供者、角色提供者、服务和存储库都倾向于到处重复.WithTenantID(...)代码,这让我意识到,99% 的时间我并不真的需要一张Users表来访问特定于某个租户的数据,因此使用单独的应用程序更有意义,并使一切变得更加简单。

感谢您的回答 - 他们让我意识到我需要重新设计。

  • 是的,这个应用程序已经发展壮大,这个决定后来让我很伤心。不可避免地,许多用户和大量数据必须在“租户”之间共享,现在存在很多库存问题。然而,这个决定可能是当时最实际的决定。 (3认同)