番外篇--Moddule Zero 版本管理与组织单位管理
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期
Moddule Zero 版本管理
2.2.1 简介
大多数SaaS(多租户)应用都会有多个版本(包),这些版本的功能点也会各不相同。因此,他们能够为他们的租户(客户)提供不同的价格和功能点选项。
关于功能点
请查阅功能点管理以理解功能点的概念
2.2.2 版本实体
版本是一个简单的实体,代表了一个应用的版本(包)。它有Name(名称)和DisplayName(显示名称)属性。
2.2.3 版本管理器
版本管理器是一个用来管理版本的领域服务:
public class EditionManager : AbpEditionManager
{
}
它继承自AbpEditionManager类。你可以注入并用版本管理器来创建、删除、更新版本。而且,版本管理器也被用于管理版本的功能点。它的内部缓存了版本的功能点以实现更好的性能。
Moddule Zero 版本管理
2.4.1 简介
组织单位(OU)用于给组用户和实体分层
2.4.2 组织单位实体
一个OU由组织单位实体来展现。该实体基本的属性如下:
- TenantId:OU的租户Id,host的组织单位的TenantId可以为空。
- ParentId:父OU的Id,根OU的ParentId可以为空。
- Code:租户下唯一的层级字符串。
- DisplayName:OU的显示名称。
组织单位实体的主键(Id)是长整型,该实体从FullAuditedEntity继承,FullAuditedEntity提供了审计信息并实现了软删除接口。
1. 组织单位树
由于一个OU可以有父级OU,一个租户下所有的OU是树形结构,该树有如下规则:
- 可以有多个根节点(根节点的ParentId为空)
- 树的最大深度被定义为一个常量OrganizationUnit.MaxDepth,它的值是16。
- 第一层级子OU数有限制(由于固定的OU编码单位长度的原因,下面有相关解释)
2. OU编码
OU编码有组织单位管理器自动创建和维护,OU编码是类似下面的字符串:
"00001.00042.00005"
该编码可以轻易实现递归查询数据库中所有的子OU,该编码有如下规则:
- 对于某个租户来说,它是唯一的。
- 一个父OU的所有子OU的编码都以父OU的编码开头。
- 它的固定长度基于树中的OU层级决定,参见示例代码。
- 尽管OU编码是唯一的,但是在你移动一个OU的情况下它能被改变,因此我们应该通过OU的Id来引用OU,而不是OU的编码。
2.4.3 组织单位管理器
组织单位管理器类可以被注入并用于管理OU,常见用例如下:
- 创建、更新、删除一个OU。
- 在OU树中移动一个OU。
- 获取OU树及节点的信息。
1. 多租户
组织单位管理器被设计用来为单租户使用,它默认为当前租户使用。
2.4.4 常见用例
以下是OU的常见用例,相关示例的源代码请点这里。
1. 创建属于某个组织单位的实体
OU最明显的用例是将实体分配给某个OU,例如:
public class Product : Entity, IMustHaveTenant, IMustHaveOrganizationUnit
{
public virtual int TenantId { get; set; }
public virtual long OrganizationUnitId { get; set; }
public virtual string Name { get; set; }
public virtual float Price { get; set; }
}
我们简单地创建了OrganizationUnitId这个属性用于将实体分配给某个OU。IMustHaveOrganizationUnit接口定义了OrganizationUnitId属性。
我们不是必须要实现这个接口,但是它被建议实现来作为一个标准。另外还有一个IMayHaveOrganizationId接口,这个接口定义了可为空的OrganizationUnitId属性。
现在我们就可以把一个产品关联到某个OU并且查询某个指定OU的相关产品了。
注意:在多租户应用中,产品实体拥有一个TenantId属性(它是IMustHaveTenant接口的一个属性)来区分不同租户的产品。如果你的应用不是多租户的应用,你就不需要这个接口及其相关的属性。
2. 获取某个组织单位内的实体
获取某个组织单位内的实体很简单,请看如下领域服务中的示例代码:
public class ProductManager : IDomainService
{
private readonly IRepository<Product> _productRepository;
public ProductManager(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public List<Product> GetProductsInOu(long organizationUnitId)
{
return _productRepository.GetAllList(p => p.OrganizationUnitId == organizationUnitId);
}
}
像上面代码里那样,我们只需要简单地加一个谓词Product.OrganizationUnitId。
3. 获取某个组织单位及其子组织单位内的实体
当我们想获取某个组织单位及其子组织单位内的实体的时候,OU编码就可以帮我们实现这个功能了。
public class ProductManager : IDomainService
{
private readonly IRepository<Product> _productRepository;
private readonly IRepository<OrganizationUnit, long> _organizationUnitRepository;
public ProductManager(
IRepository<Product> productRepository,
IRepository<OrganizationUnit, long> organizationUnitRepository)
{
_productRepository = productRepository;
_organizationUnitRepository = organizationUnitRepository;
}
[UnitOfWork]
public virtual List<Product> GetProductsInOuIncludingChildren(long organizationUnitId)
{
var code = _organizationUnitRepository.Get(organizationUnitId).Code;
var query =
from product in _productRepository.GetAll()
join organizationUnit in _organizationUnitRepository.GetAll() on product.OrganizationUnitId equals organizationUnit.Id
where organizationUnit.Code.StartsWith(code)
select product;
return query.ToList();
}
}
首先,我们获取指定的OU的编码,然后我们创建一个带join和StartsWith(code)条件的LINQ查询(StartsWith创建了sql里的like查询)。因此,我们能够向下按层级获取一个OU及其子OU所属的产品。
4. 过滤某个用户的实体
我们可能希望获取某个用户所属的OU(一个或多个)内的所有产品,代码如下:
public class ProductManager : IDomainService
{
private readonly IRepository<Product> _productRepository;
private readonly UserManager _userManager;
public ProductManager(
IRepository<Product> productRepository,
UserManager userManager)
{
_productRepository = productRepository;
_organizationUnitRepository = organizationUnitRepository;
_userManager = userManager;
}
public async Task<List<Product>> GetProductsForUserAsync(long userId)
{
var user = await _userManager.GetUserByIdAsync(userId);
var organizationUnits = await _userManager.GetOrganizationUnitsAsync(user);
var organizationUnitIds = organizationUnits.Select(ou => ou.Id);
return await _productRepository.GetAllListAsync(p => organizationUnitIds.Contains(p.OrganizationUnitId));
}
}
我们通过简单地查询获取了用户所属OU的Id列表,然后我们使用Contains条件来查询产品。当然,我们可以创建LINQ关联查询来获取相同的列表。
我们也可能会希望获取某个用户所属的OU(一个或多个)内及其子OU内的所有产品
public class ProductManager : IDomainService
{
private readonly IRepository<Product> _productRepository;
private readonly IRepository<OrganizationUnit, long> _organizationUnitRepository;
private readonly UserManager _userManager;
public ProductManager(
IRepository<Product> productRepository,
IRepository<OrganizationUnit, long> organizationUnitRepository,
UserManager userManager)
{
_productRepository = productRepository;
_organizationUnitRepository = organizationUnitRepository;
_userManager = userManager;
}
[UnitOfWork]
public virtual async Task<List<Product>> GetProductsForUserIncludingChildOusAsync(long userId)
{
var user = await _userManager.GetUserByIdAsync(userId);
var organizationUnits = await _userManager.GetOrganizationUnitsAsync(user);
var organizationUnitCodes = organizationUnits.Select(ou => ou.Code);
var query =
from product in _productRepository.GetAll()
join organizationUnit in _organizationUnitRepository.GetAll() on product.OrganizationUnitId equals organizationUnit.Id
where organizationUnitCodes.Any(code => organizationUnit.Code.StartsWith(code))
select product;
return query.ToList();
}
}
我们在LINQ关联查询声明中组合使用了Any和StartsWith条件。
当然,可能会有更复杂的需求,但是都能用LINQ和SQL来实现。
2.4.5 设置
我们可以注入并使用IOrganizationUnitSettings接口来获取组织单位设置值。当前,只有一个设置能被按需改变:
- MaxUserMembershipCount:一个用户所属组织单位的数量的最大值。
- 默认值是int.MaxValue,即无限制。
- 设置的名称是一个常量,被定义在AbpZeroSettingNames.OrganizationUnits.MaxUserMembershipCount中。
你可以通过设置管理改变设定值
番外篇--Moddule Zero 版本管理与组织单位管理的更多相关文章
- 番外篇--Moddule Zero多租户管理
番外篇--Moddule Zero多租户管理 2.1.1 关于多租户 强烈建议阅读这个文件前阅读多租户文档. 2.1.2 启用多租户 ASP.NET Boilerplate和module-zero可以 ...
- 番外篇--Moddule Zero安装
Moddule Zero 安装 1.2.1 从模板创建 使用ABP和module-zero开始一个新项目最简单的方式是使用启动模板.详细了解请参考启动模板文档. 1.2.2 手动安装 如果你有一个预先 ...
- 番外篇--Moddule Zero启动模板
1.3 ABPZero - 启动模板 1.3.1 简介 使用ABP和moudle-zero开始一个新项目的最简单的方式是在模板页创建模板.记住要勾选 Include module zero. 在创建并 ...
- 番外篇--Moddule Zero介绍
1.1 ABPZero - 概述 介绍 微软ASP.NET身份框架 权限 会话 角色管理 默认角色 用户管理 多租户 设置管理 审计日志 1.1.1 介绍 Modulde Zero实现了ASP.NET ...
- C++雾中风景番外篇:理解C++的复杂声明与声明解析
在学习C系列语言的过程之中,理解C/C++的复杂声明一直是初学者很困扰的问题.笔者初学之时也深受困扰,对很多规则死记硬背.后续在阅读<C专家编程>之后,尝试在编译器的角度来理解C/C++的 ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权
iOS冰与火之歌(番外篇) 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权 蒸米@阿里移动安全 0x00 序 这段时间最火的漏洞当属阿联酋的人权活动人士被apt攻击所使用 ...
- 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV
这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...
- 可视化(番外篇)——在Eclipse RCP中玩转OpenGL
最近在看有关Eclipse RCP方面的东西,鉴于Gephi是使用opengl作为绘图引擎,所以,萌生了在Eclipse RCP下添加画布,使用opengl绘图的想法,网上有博文详细介绍这方面的内容, ...
随机推荐
- Golang丰富的I/O----用N种Hello World展示
h1 { margin-top: 0.6cm; margin-bottom: 0.58cm; direction: ltr; color: #000000; line-height: 200%; te ...
- 在win7下用net命令无法实现对用户的创建(未完成)
============================================================================================= 201307 ...
- Linux整合Apache和SVN
1.安装APR-1.2.7和APR-util-1.2.7 (下载地址:http://apr.apache.org/) #tar zxvf apr-1.2.7.tar.gz #cd apr-1. ...
- 完美解决浮动IE6 7中的兼容性BUG问题
想要创建出漂亮的网页设计,除了要认真学习每一个html和CSS代码之外,不可能不去了解一下臭名昭著的IE6和更早的那些IE浏览器的坏脾气,因为你本来写出的规规矩矩的代码,漂亮的设计就此就要完成了,却发 ...
- tomcat发布项目绑定域名总结
现在很多的公司的网站都是用tomcat作为应用服务区的,可是对于初学者,8080端口号是如何去掉的,这些网站是如何和域名绑定到一起的呢?一个tomcat是如何绑定多域名?并且这些域名是如何对应不同的项 ...
- 对DataTable(或者DataSet)修改后,提交修改到数据库
http://blog.csdn.net/nidexuanzhe/article/details/8228832 说明:通常我们在做数据库交互时,并不一定要使用特定的SQL语句来更新数据,.NET F ...
- 微信小程序参数二维码6问6答
微信小程序参数二维码[基础知识篇],从6个常见问题了解小程序参数二维码的入门知识. 1.什么是小程序参数码? 微信小程序参数二维码:针对小程序特定页面,设定相应参数值,用户扫描后进入相应的页面. 2. ...
- openldap 编译报错MozNSS not found
openldap 编译报错 1)报错 MozNSS not found - please specify the location to the NSPR and NSS header files i ...
- IDEA第八章----远程调试
大家有没有遇到相同分支的代码在本地就是没有问题的,但是到测试环境死活不能实现功能,且还不报错.通常我们的解决办法就是打日志,然后一点一点跟踪日志. 这时我们在想如果也可以按照本地一样能断点测试的程序就 ...
- Koa2和相关资料
koa2是什么我就不介绍,这里只是收集一些有用的资料,koa这里默认就指koa2了额. koa介绍 koa(GitHub) koa(npm) 文档 Usage Guide Error Handling ...