X-Admin&ABP框架开发-租户管理
软件即服务概念的推动,定制化到通用化的发展,用一套代码完成适应不同企业的需求,利用多租户技术可以去做到这一点。ABP里提供了多租户这一概念并且也在Zero模块中实现了这一概念。
一、多租户的概念
单部署-单数据库:部署应用程序的单个实例和单个数据库。在每个数据表(关系型数据库)里用一个TenantId(租户Id或类似的如企业Id)字段来隔离区分每个租户数据。
单部署-多数据库:部署应用的单一实例,用一个主(宿主)数据库存储租户元数据(像租户名和子域),并为每个租户建立并维护一个隔离的数据库。操作上通过识别当前租户并从主数据库中读取相对应的存储数据库地址,切换到该租户独有的数据库中执行操作。
多部署-多数据库:为每个租户部署应用的一个实例并使用一个独立的数据库,那么我们就可以在一台服务器上为多个租户服务,只需确保相同应用的多个实例在一个服务器的环境下不会互相冲突就行。
还有两种多租户形式,诸如单部署-混搭数据库、集群部署-单/多/混搭数据库,不再提及,ABP针对于这五种多租户形式都可以使用。
宿主与租户:对于这两个概念,最好的理解方式便是酒店,酒店老板即是宿主,租户只拥有房间权限,酒店老板可以提供管理所有租户和房间。
二、ABP中多租户配置
1、启用/禁用多租户
如果不需要多租户,比如说没有多租户情形,应用部署在企业私有服务器上,那么也可以不考虑多租户的使用,可以在ABP中关闭多租户(尽管关闭了,但默认还是会使用一个租户,默认租户Id为1,此时只有这个默认租户没有宿主)。在WebCoreModule中PreInitialize方法内可以添加如下代码启用或关闭多租户,默认是启用的。
public override void PreInitialize()
{
... Configuration.MultiTenancy.IsEnabled = true; ...
}
2、侦测当前租户并在Session中获取租户
ABP中租户名称是唯一的,对于识别当前租户或是宿主身份,ABP没有使用Asp.Net 提供的Session,声明了IAbpSession接口并提供了默认的实现(ClaimAbpSession)去测定当前租户信息,按照如下思路去确定租户。
- 如果当前用户登录了系统,那么可以从当前用户的声明信息中读取到当前租户信息,如果没有读取到租户信息,那么可以断定是宿主。
- 如果当前用户没有登录系统,那么会有几种方式去获取,如果以下几种方式仍未获取到租户Id,则认为是使用宿主登录。
- 从当前域名或是子域名去获取域名名称,然后通过租户仓储去查询是否存在相关的域名或子域名存在则可以确定租户Id。
- 从Http请求头中获取在ABP中默认配置项Abp.TenantId(该配置项可更换名称)。
- 从Http请求的cookie中获取Abp.TenantId
IAbpSession声明了获取当前用户和租户信息的方法,该方法允许我们获取当前登录的用户及当前的租户信息。并且获取到的信息按照不同的规则,有着不同的作用。
- 如果获取到的用户和租户Id都是空的,那么意味着当前用户没有登录系统,因此也无法断定出当前是宿主还是租户。
- 如果用户Id是空的,但是租户Id不是空的,那么可以知道是哪个租户,但是用户仍然是没有登录的,只是选择了租户。
- 如果用户Id不是空的,但是租户Id是空的,那么可以知道是用户使用宿主登录了系统。
- 如果用户Id且租户Id不是空的,那么就知道是选择了租户并且是租户中的某个用户登录了系统。
3、数据过滤
如果使用了多租户,那么在读取数据时,会依据当前租户Id加上额外的过滤条件,这一点ABP已经处理好了,我们无需在linq中敲代码,但是有个前提条件是,读取数据的这个实体有设置多租户。
1、如果实体使用的是IMustHaveTenant接口,那么读取时会依照当前租户Id进行条件过滤。
2、如果实体使用的是IMayHaveTenant接口,那么读取到的数据会依照当前租户Id的有无值进行区分,如果当前租户Id为空,那么将读取到宿主的数据,如果租户Id不为空,则读取相应租户数据。
3、如果实体没使用这两个接口,则读取到的数据不区分宿主和租户。
这两个接口使用场景:如果是宿主和租户都需要的,比如角色、用户、部门等,那么使用IMayHaveTenant接口,如果仅是租户所需要的那只需使用IMustHaveTenant接口。
4、宿主与租户间切换
此处切换可以这么理解,给我一个其它租户Id,我可以在我的租户中获取到其它租户的数据,相应的,其它租户也可以获取到我租户的数据,或是宿主获取租户数据。如果不给定租户Id,租户可以获取宿主数据。
public class ProductService : ITransientDependency
{
private readonly IRepository<Product> _productRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager; public ProductService(IRepository<Product> productRepository, IUnitOfWorkManager unitOfWorkManager)
{
_productRepository = productRepository;
_unitOfWorkManager = unitOfWorkManager;
} [UnitOfWork]
public virtual List<Product> GetProducts(int tenantId)
{
using (_unitOfWorkManager.Current.SetTenantId(tenantId))
{
return _productRepository.GetAllList();
}
}
}
三、配置一个多租户实体
基于之前的数据字典进行改造,以便适用于多个租户使用,并且考虑到宿主无需使用数据字典,将其继承IMustHaveTenant接口后,更新数据库便可。
public class DataDictionary : Entity<long>, IMustHaveTenant
{
public const int MaxNameLength = ; /// <summary>
/// 租户Id
/// </summary>
public int? TenantId { get; set; } /// <summary>
/// 字典类型
/// </summary>
[StringLength(MaxNameLength)]
public string TypeName { get; set; } /// <summary>
/// 关联数据字典项
/// </summary>
public virtual ICollection<DataDictionaryItem> DataDictionaryItem { get; set; }
}
我设置了默认当前租户,并且不提供选择租户的页面,通过Url去区分宿主和默认租户,登录当前租户账号后,查看当前网站内的数据字典看到之前已有数据全部消失,获取数据字典数据时,默认是ABP将当前租户Id带入作为查询条件了。
修改添加方法,添加当前租户Id的赋值,再次为当前租户添加几条相应的数据字典,页面中即可存在相关数据了。
dataDictionary.TenantId = AbpSession.TenantId.Value;
最后两条数据是指定租户Id为1下的,之前的数据可以手动清除。
至此,对于ABP中租户的相关使用了解的清楚了,对于多租户下数据存储量大,拆分成集群部署-多数据库情形没有做尝试,希望有机会可以使用一番。
仓库地址:https://gitee.com/530521314/Partner.Surround.git
2020-01-11,望技术有成后能回来看见自己的脚步
X-Admin&ABP框架开发-租户管理的更多相关文章
- X-Admin&ABP框架开发-设置管理
在网站开发中,设置是不可缺少的一环,如用户设置.系统设置.甚至是租户设置等.ABP对于设置的管理已经做了很好的处理,我们可以借助巨人的力量来完成我们的冒险. ABP官网地址:https://aspne ...
- ABP Zero 多租户管理
ABPZero - 多租户管理 启用多租户 ASP.NET Boilerplate和module-zero可以运行多租户或单租户模式.多租户默认为禁用.我们可以在我们的模块PreInitialize方 ...
- X-Admin&ABP框架开发-RBAC
在业务系统需求规划过程中,通常对于诸如组织机构.用户和角色等这种基础功能,通常是将这部分功能规划到通用子域中,这也说明了,对于这部分功能来讲,是系统的基石,整个业务体系是建立于这部分基石之上的,当然, ...
- X-Admin&ABP框架开发-版本管理
多租户系统中,针对于不同租户开放不同功能,或是按照不同功能进行收费管理,需要从宿主本身去管理租户的版本信息,如同酒店人员对不同房间收取不同费用,依据房间内部设施,房间大小等设置不同收费标准.Abp系统 ...
- X-Admin&ABP框架开发-消息通知
业务型网站使用过程中,消息通知是一个不可或缺的功能,采用站内通知.短信通知.邮件通知.微信通知等等各种方式都有,ABP框架对这部分工作已经封装的很好了,站在巨人的肩膀上,一览全貌,带来的就是心情舒畅. ...
- X-Admin&ABP框架开发-系统日志
网站正常运行中有时出现异常在所难免,查看系统运行日志分析问题并能够根据错误信息快速解决问题尤为重要,ABP对于系统运行日志这块已经做了很好的处理,默认采用的Log4Net已经足够满足开发过程中的需要了 ...
- ABP框架 - 多租户
文档目录 本节内容: 什么是多租户 多部署 - 多数据库 单部署 - 多数据库 单部署 - 单数据库 单部署 - 混数据库 多部署 - 单/多/混 数据库 ABP中的多租户 启用多租户 宿主与租户 会 ...
- X-Admin&ABP框架开发-代码生成器
在日常开发中,有时会遇到一些相似的代码,甚至是只要CV一次,改几个名称,就可以实现功能了,而且总归起来,都可以由一些公用的页面更改而来,因此,结合我日常开发中使用到的页面,封装一个适合自己的代码生成器 ...
- X-Admin&ABP框架开发-数据字典
在业务型的系统开发中,我们需要维护各种个样的类型,比如客户类型.客户行业.商品类型等等,这些类型往往信息量不多,并且相似度极高,如果采用一类型一表去设计,将会造成极大的工作量,通过将这部分类型的信息进 ...
随机推荐
- Android 隐藏EditText的焦点
在页面的开发过程中,我们可能会遇到这样的情况,打开某个页面(Activity)时,如果该页面中有EditText组建,则会自动弹出软键盘(因为该EditText自动获取焦点了),这样很容易影响用户体验 ...
- hihocoder 1272 买零食
#1272 : 买零食 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho很喜欢在课间去小卖部买零食.然而不幸的是,这个学期他又有在一教的课,而一教的小卖部姐姐以冷若冰 ...
- Study in JI During the Summer Vacation
15/07/2019-21/07/2019 Task List: 1.uow homework including vocabulary and listening 2.ASL's dictation ...
- H3C 在网络中的正确位置配置ACL包过滤
- H3C 最大跳数16导致网络尺度小
- 学习vue就是那么简单,一个简单的案例
vue是前端兴起的一个javascript库,相信大家都使用过jQuery,虽然vue和jQuery没有可比性,但从熟悉的角度去理解新的东西或许会容易接受一些,有时候由于思想和模式的转变会带来阵痛,但 ...
- 解决浏览器中点击input输入框时,placeholder的值不消失的方法
版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/lianwenxiu/article/det ...
- Spring Security 学习笔记-securityContext过滤器
位于过滤器顶端,第一个起作用的过滤器.SecurityContextPersistenceFilter 在执行其他过滤器之前,率先判断用户的session中是否已经存在一个SecurityContex ...
- 【codeforces 750C】New Year and Rating
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- dotnet 手动解决 json 解析中不合法字符串
如果使用 Newtonsoft Json 解析字符串,字符串里面有不清真的格式,那么默认的解析将会炸掉.如果想要自己解决字符串中的不清真格式,可以使用传入 JsonSerializerSettings ...