【发布时间】:2018-11-13 13:54:51
【问题描述】:
我需要为现有系统构建 Web API。全国各地都有各种机构,每个机构都有自己的数据库。所有数据库都在一台服务器上。所有数据库的结构都相同。所有数据库都有自己的用户名和密码。一个机构有一个或多个用户。一个用户可以属于一个或多个机构。还有一个特殊的数据库,其中包含一个所有用户表、一个所有代理表和一个用户代理桥表。
目前他们使用的是传统的 Windows 桌面应用程序。当用户设置此 Windows 程序时,他们使用用户名和密码登录。然后系统会为他们显示他们所属的所有机构的列表(通常只有一个,但一些“高级用户”可能属于少数几个)。他们选择一个机构,然后程序连接到正确的数据库。在会话的剩余时间里,用户所做的一切都将在该数据库上完成。
客户想要创建一个 Web 应用程序来最终替换 Windows 程序(两者将并行运行一段时间)。一位开发人员正在 Angular 5 中创建前端,而我正在 ASP .Net Core 2.1 中开发 API。
因此,Web 应用程序将以与 Windows 应用程序类似的方式运行。用户登录到 Web 应用程序。使用我的 Web API 的 Web 应用程序告诉 API 哪个用户刚刚登录。API 然后从存储该数据的数据库中检查该用户属于哪个机构。 API 返回用户所属的网络应用程序的代理列表。在那里,用户选择一个机构。从此时起,Web 应用程序将在所有 API 调用的标头中包含此代理 ID。 API 在收到来自 Web 应用程序的请求时,将根据请求标头中的代理 ID 知道要使用哪个数据库。
希望这是有道理的......
显然,这意味着我将不得不即时更改 DbContext 的连接字符串,具体取决于 API 必须与哪个数据库通信。我一直在研究这个问题,首先是在控制器本身上进行,这很有效,但会在我的所有控制器中涉及大量复制和粘贴反模式。所以我试图将其移至 DbContext 的 OnConfiguring 事件。我在想最好使用适当的连接字符串创建一个 DbContext 工厂来创建 DbContext。我只是有点失落。您会看到,当 Web 应用程序调用 Web api 上的端点时(假设是一个 HTTP GET 请求以获取帐户列表),这将触发 Accounts 控制器中的 HttpGet 处理程序。然后,此操作方法读取代理 ID 标头。但这一切都发生在控制器上......如果我从 DbContext 的 OnConfiguring() 事件中调用 DbContext 工厂,它必须将代理 ID(在控制器中读取)发送到工厂,以便工厂知道要创建的连接字符串。我试图不使用全局变量来保持我的类松散耦合。
除非我在管道中运行了一些服务来拦截所有请求,读取代理 ID 标头,并且这以某种方式被注入到 DbContext 构造函数中?不知道我会怎么做...
总之,我有点迷茫。我什至不确定这是否是正确的方法。我看过一些“多租户”示例,但老实说,我发现它们有点难以理解,我希望我现在可以做一些更简单的事情,随着时间的推移,据我所知.Net Core 的改进,我可以看看相应地改进代码。
【问题讨论】:
-
见下面我的回答。如果您对样本有任何疑问,请告诉我。
-
你看过SaasKit吗?
标签: asp.net-core multi-tenant asp.net-core-webapi