Bre*_*bst 3 architecture saas multi-tenant entity-framework-4.1
我已经搜索了SO和其他景点,以寻求有关我如何做到这一点的帮助.我看到许多人建议不要这样做,但我有合理而简单的原因,客户会想要这样做.
所以这就是我想要做的:
我有一个多租户应用程序,其中包含一个用于管理应用程序的多租户方面的通用框架,如数据存储位置等.每个租户都有"x"个用户可以访问租户的帐户.但是,每个租户可以将多个实例绑定到其帐户.例如,租户可能还有一个生产实例和一个测试或开发实例.每个实例与隔离数据库具有一对一的关系.我最有意义的是,我会在框架级别存储登录凭据,而不是每个单独的实例,因为这会以指数方式增加用户名和密码的数量.
设计相当简单,有一个Tenant对象,它有一组用户和一组实例.将有一个额外的交叉引用对象,它将授权用户访问特定实例.例如,我可能只允许大多数租户用户访问生产实例,但对于系统管理员,他们可以完全访问所有实例.
我挂掉的部分是这样的:
存储在所有实例中的用户信息实际上应该只包含用户名和密码等基础知识,因为名称,电话号码等详细信息都应该驻留在特定于实例的数据库中.更重要的是,用户将在每个实例中与另一个实体建立一对多的关系,无论是员工,个人还是联系对象.
我的问题变成了:
根据设计,我有什么是跨模型(框架,实例)链接对象(用户和员工)的最简单方法?更重要的是,如何在所有实例中保持数据更改或修改同步,或者我是否应该担心?
我真的很感激任何人都可以提供任何反馈,特别是如果你已经解决了这样的问题或者有这种模型的经验.我非常注重现有的设计,因为它必须以这种方式工作以满足客户的要求,我需要使技术满足要求.
感谢您的专业知识!
黑雁
Tra*_*lig 11
听起来这里有三种相互关联的东西,即使问题只围绕一个问题:
可能有几种方法可以解决每一种方法,但这就是我要做的事情:
数据如何存储在数据库中?
由于每个租户 - 应用程序实例有一个数据库(每个"环境" - 生产,测试等都是租户实例)并且您拥有与所有这些实例相关的数据,我会存储"常见"数据在一个单独的数据库中.
我们将该数据库称为SystemConfiguration数据库.在那,你有:
将此SystemConfiguration数据库拆分为自己的东西意味着您不必尝试在任何地方保持公共用户信息的同步.如果存在每个实例的用户信息(例如,用户设置或其他内容),那么它将进入实例数据库,但名称,密码哈希等都进入该中央数据库.
从技术上讲,您可以通过其他方式对其进行分区,例如拥有单独的用户数据库,并且只在SystemConfiguration数据库中保留租户/系统配置,但这至少可以为您提供这个想法.
如果租户决定离开,那么查询与特定租户相关的任何信息并从SystemConfiguration数据库中导出它将非常容易.与实例数据库中特定于租户的数据量相比,应该没有太多.
您如何确保每个用户只能访问他们拥有权利的实例?
我认为基于声明的身份验证/授权会使这个问题变得更加简单.如果您不熟悉声明,那么我们的想法是,不是拥有用户所在的"角色"的静态列表,而是拥有与每个用户关联的名称/值对的字典.字典是用户的"声明集",每个名称/值对都是"声明".角色的好处是值可以是任何值,包括列表.
用户在进行身份验证时,将获得一组声明,包括其用户名,其姓/名以及他们可以访问的实例列表.
之后,只需根据当前实例的ID检查用户的声明即可.如果经过身份验证的用户无权访问该实例,请阻止他们.
将它带回数据存储 - 从SystemConfiguration数据库生成一组声明将是一个简单的查询.
有关基于声明的身份以及如何使用Windows Identity Foundation在应用程序中使用它的更多信息,请查看由Vittorio Bertocci 编写的Windows Identity Foundation.这是一本好书...而且它几乎是关于WIF的唯一一本书.
如何将数据映射到对象以便在代码中使用?
此时,它更多地是关于您希望从代码中获取数据的视图,而不是关于数据存储结构的视图.如果你想让一个Tenant对象中有一个IEnumerable <User>,那么这就是你所选择的ORM.
我可能建议至少在SystemConfiguration数据库周围使用服务合同进行包装操作,因此如果您更改下面的数据,则可以在服务层而不是消费代码中调整ORM.接口!
无论如何,这里的重点是我不会尝试将数据存储基于您使用数据的方式.
最后,如果您的实例中需要用户或租户信息,您最终会有一些查询与SystemConfiguration数据库通信,并且会与租户实例数据库进行对话.没关系.只要您为所有内容使用全局唯一标识符,就可以将用户从一个数据库绑定到另一个数据库中的某个设置或值,只需按ID即可.参照完整性有点难以维护,但它比在一堆实例数据库中维护数据同步更容易.
这可能是在服务中包装内容的另一个原因.例如,如果您有"UserSettings"服务,则您的合同可能会要求提供租户实例ID和用户ID,并返回设置列表.在幕后,该服务可以从SystemConfiguration查询数据,将其映射到适当的实例数据库,并返回合并的数据集 - 对调用代码都是透明的.另一方面,当您只更改对象的值并想要提交更改时,您没有得到一些ORM为您提供的"Update()"方法.这是一个权衡,你是否想要将ORM处理为合规以实现这一点.