我需要为现有系统构建一个web api。全国各地都有不同的机构,每个机构都有自己的数据库。所有数据库都在一台服务器上。所有数据库的结构都是相同的。所有数据库都有自己的用户名和密码。一个机构有一个或多个用户。用户可以属于一个或多个机构。还有一个特殊的数据库,其中包含一个包含所有用户的表、一个包含所有代理的表和用户代理桥表。
目前他们正在使用传统的windows桌面应用程序。当用户设置此windows程序时,他们将使用用户名和密码登录。然后,系统会为他们显示他们所属的所有机构的列表(通常只有一个,但一些“超级用户”可能属于少数)。他们选择一个代理,然后程序连接到正确的数据库。对于会话的其余部分,用户所做的一切都将在该数据库上完成。
客户端希望创建一个web应用程序来最终替换windows程序(这两个程序将同时运行一段时间)。一个开发人员正在Angular5中创建前端,我正在ASP.NET Core2.1中开发API。
因此,web应用程序将以类似于windows应用程序的方式运行。用户登录到Web应用程序。使用我的web api的web应用程序告诉api哪个用户刚刚登录。然后,api从存储该数据的数据库中检查该用户属于哪个机构。api返回用户属于web应用程序的代理列表。在那里,用户选择一个代理。从现在起,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核心知识的提高,我可以考虑相应地改进代码。