Asp.net mvc 共享数据的多租户应用程序(Asp net mvc+;实体框架+;Sql Server)

Asp.net mvc 共享数据的多租户应用程序(Asp net mvc+;实体框架+;Sql Server),asp.net-mvc,entity-framework,multi-tenant,Asp.net Mvc,Entity Framework,Multi Tenant,我正在开发一个非常复杂的多租户应用程序架构 3种完全不同的应用程序 许多客户使用的不仅仅是一种类型的应用程序;有3种不同的应用程序 应用A、应用B、应用C 每个应用程序都是多租户的 每个应用都有自己的客户 应用程序A -客户A1 -客户A2 应用程序B -客户B1 -客户B2 附录C -客户C1 -客户C2 共享信息 许多信息在不同的应用程序之间共享 “客户A1”需要操作或仅查看“客户C1”拥有的数据 问题 假设我使用的是Asp net mvc、EF和Sql Server。 正确的实现是

我正在开发一个非常复杂的多租户应用程序架构

3种完全不同的应用程序 许多客户使用的不仅仅是一种类型的应用程序;有3种不同的应用程序

应用A、应用B、应用C

每个应用程序都是多租户的 每个应用都有自己的客户

应用程序A -客户A1 -客户A2

应用程序B -客户B1 -客户B2

附录C -客户C1 -客户C2

共享信息 许多信息在不同的应用程序之间共享

“客户A1”需要操作或仅查看“客户C1”拥有的数据

问题 假设我使用的是Asp net mvc、EF和Sql Server。 正确的实现是什么

一个站点和多个区域? 创建多个站点? 多分贝?只有一分贝?过滤?Sql筛选视图

一些应用程序示例?

编辑


而且。。。将业务逻辑放在何处?

理想情况下,在具有单个应用程序的多租户服务器中,您希望每个租户拥有物理上不同的数据库,而不仅仅是指定数据所属租户的列

但无论哪种方式,您都必须确保所有数据库函数使用正确的数据库连接或租户列键。这才是真正的问题

确保这一点的方法是,每个做出此决定的应用程序只有一个函数,并且确保所有数据库函数在没有调用此函数时失败(直接或间接,如下所示)

e、 g.使用global.asax AuthenticateRequest或BeginRequest函数中的MVC,您可以验证用户是谁,然后计算他们需要使用哪个数据库连接,或者他们必须在该请求的每个查询中使用哪个租户列键。然后将其存储在会话变量等中


如果你有三个应用程序,我会创建三个独立的站点。他们可以通过共享项目共享公共类。如果它们可以单独部署

,这通常是比较容易的。这是一个具体的答案,但也只是一些在设计时可能会考虑的方面。

关于共享信息,我认为这里最重要的部分是定义客户之间的关系以及每个客户对其他客户的角色和权利。最好的方法是首先确定可以做什么

例如:

Read Only|cust1|cust2|cust3
---------+-----+-----+-----
customer1| 1   | 1   | 0
customer2| 0   | 1   | 0
customer3| 1   | 0   | 1

Write    |cust1|cust2|cust3
---------+-----+-----+-----
customer1| 1   | 1   | 0
customer2| 0   | 1   | 0
customer3| 0   | 0   | 1
因此,在上述情况下,customer1可以读取和写入(更新)customer2的数据

尽管如此,主要问题是对这些关系(即共享信息)进行建模。使用@TFD的建议,可以将这些关系加载到会话中,以便在客户与相关租户id一起登录时使用

(根据提供的信息,我的另一个倾向是,这可能是每个应用程序的问题,而不仅仅是客户的问题。为了说明这一点,请将上表中的“cust”值替换为
App

为每个应用程序创建单独的站点,因为我假设每个应用程序都有一个独特的用途,尽管有共享的功能

如果存在其他跨数据关系,可能需要不同的配置数据库。DB将存储每个应用程序的所有租户信息(包括与其他应用程序的关系)。这个建议的原因是,据我所见,您有三个独立的多租户应用程序,它们使用共享数据库方法相互独立,但每个应用程序都需要在某种程度上与另一个应用程序交互。

对于数据库中的客户,我建议将“客户”表限制在Config数据库中。然后,您可以根据每个应用程序的要求拥有一个内容数据库。

您可以有多种方法-由于应用程序是数据驱动的,因此构建一个数据库设计来保护数据是有意义的,即使在应用程序出现错误的情况下也是如此

一种方法是确保有用于访问任何表的存储过程,并且安全逻辑内置于存储过程中。您可以确保每个客户使用不同的db用户名,并且此db用户名在映射表中映射到该租户id。然后,存储的proc可以始终检查所请求/修改的数据是否实际属于映射到运行proc的db用户的租户id(通过使用上下文信息)

然后,您将需要某种方法来确保应用程序创建的db连接只使用映射到该租户id的相应用户名。这意味着您需要多个存储过程来提供此信息(可能以用户名/id作为输入),并且此存储过程应可通过公共db用户名执行。请记住,这是唯一一个需要将执行特权赋予此公共db用户的存储过程


这可能看起来像是编写了一堆额外的代码,但它确实有助于了解您的数据库将拒绝错误的请求,即使是由于应用程序错误。你唯一需要非常非常小心的地方就是为该用户id获取正确的租户db用户名和密码的地方,这应该是非常可能的

我的建议是使用带银灯的棱镜和MVVM设计模式。PRISM是为这样一种复合应用程序而设计的,其中每个应用程序都是独立的,还可以通过PRISM公开的事件相互通信。

我建议您首先构建自己的多租户工程堆栈(框架)在.Net之上,它将处理多租户的所有要求,包括租户数据隔离、支持水平扩展、基于租户上下文和用户角色的视图过滤、租户数据模型扩展、租户用户界面定制、基于ro的访问限制