Module-Zero之组织单元(OU)管理【新增】
2016-01-24 13:46
281 查看
返回《Module Zero学习目录》
概览介绍
OrganizationUnit实体
OrganizationUnit管理者
公共用例
设置
TenantId:该OU的租户Id。对于租主的OU可以为null。
ParentId:父OU的Id。如果该OU是根OU,那么可以是null。
Code:对于每个租户都唯一的有层次的字符串码。
DisplayName:OU的显示名称。
OrganizationUnit实体的主键(Id)是long类型的,OrganizationUnit实体是从提供了审计信息的FullAuditedEntity派生的,而且实现了 ISoftDelete接口(因此,OU是不能从数据库中真正删除的,只是软删除)。
可以有不止一个根(根的ParentId为null)。
根的最大深度定义为OrganizationUnit.MaxDepth常量,值为16。
一个OU的第一层的孩子数量是有限制的(因为OU代码单元长度是固定的,下面有解释)。
这个代码可以轻松地查询一个OU的所有孩子(递归地查询)的数据库数据,该代码的一些规则如下:
对于租户是唯一的。
相同OU的所有孩子的代码以父OU代码作为开头。
基于OU在树中的层级,它会有一个固定长度。
虽然OU代码是唯一的,但如果你移动了一个OU,那么它是可修改的。因此,我们应该通过Id来引用一个OU,而不是代码(Code)。
创建,更新或删除一个OU
在OU树中移动一个OU
获取关于OU树和OU项的信息
我们创建了OrganizationUnitId属性将一个实体赋予一个OU。 IMustHaveOrganizationUnit定义了OrganizationUnitId属性。我们不必实现该接口,但是建议提供标准化。除此之外,还有一个IMayHaveOrganizationId,该接口提供了一个nullable(可空)的OrganizationUnitId属性。
现在,我们可以将一个Product关联到一个OU,并且查询一个特定OU的产品。
注意:Product实体有 TenantId(它是IMustHaveTenant接口中定义的属性)属性来区分多租户应用中不同租户的产品(请看多租户博客)。如果你的应用不是多租户,那么你不需要这个接口和属性。
我们可以对Product.OrganizationUnitId简单地写一个断言,如上所示。
首先,我们获得给定OU的Code。然后,我们创建了一个具有join和StartsWith(code)条件(在sql中StartsWith创建一个
我们先找到该用户OU的Id,然后获取Products时使用了Contains条件。当然,我们可以创建一个具有join的LINQ查询来获得相同的列表。
我们可能想要获取包括子OU的用户OU的Products:
我们将具有
当然,也可能有更复杂的需求,但是所有的需求都可以使用LINQ或SQL完成。
MaxUserMembershipCount:一个用户最大允许的关系数量。默认值是
你可以使用设置管理者修改设置值。
概览介绍
OrganizationUnit实体
OrganizationUnit管理者
公共用例
设置
概览介绍
组织单元(Organization Unit【简称OU】)可以有层次地给用户和实体分组。OrganizationUnit实体
一个OU是通过OrganizationUnit实体表示的。该实体的基本属性如下:TenantId:该OU的租户Id。对于租主的OU可以为null。
ParentId:父OU的Id。如果该OU是根OU,那么可以是null。
Code:对于每个租户都唯一的有层次的字符串码。
DisplayName:OU的显示名称。
OrganizationUnit实体的主键(Id)是long类型的,OrganizationUnit实体是从提供了审计信息的FullAuditedEntity派生的,而且实现了 ISoftDelete接口(因此,OU是不能从数据库中真正删除的,只是软删除)。
组织树(Organization Tree)
因为一个OU可以有一个父亲,所以一个租户的所有OU是在一个树形结构中的。这棵树有一些规则:可以有不止一个根(根的ParentId为null)。
根的最大深度定义为OrganizationUnit.MaxDepth常量,值为16。
一个OU的第一层的孩子数量是有限制的(因为OU代码单元长度是固定的,下面有解释)。
OU代码
OU代码是OrganizationUnit管理者自动生成、维护的,它是一个字符串,有点像"00001.00042.00005"。这个代码可以轻松地查询一个OU的所有孩子(递归地查询)的数据库数据,该代码的一些规则如下:
对于租户是唯一的。
相同OU的所有孩子的代码以父OU代码作为开头。
基于OU在树中的层级,它会有一个固定长度。
虽然OU代码是唯一的,但如果你移动了一个OU,那么它是可修改的。因此,我们应该通过Id来引用一个OU,而不是代码(Code)。
OrganizationUnit管理者
OrganizationUnitManager类可以被注入,用于管理OU。公共用例是:创建,更新或删除一个OU
在OU树中移动一个OU
获取关于OU树和OU项的信息
多租户
OrganizationUnitManager是为单租户设计的,默认对 当前的租户有效。公共用例
这里,我们会看到OU的公共用例。你可以点击这里找到样例的源代码。创建属于OU的实体
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,该接口提供了一个nullable(可空)的OrganizationUnitId属性。
现在,我们可以将一个Product关联到一个OU,并且查询一个特定OU的产品。
注意:Product实体有 TenantId(它是IMustHaveTenant接口中定义的属性)属性来区分多租户应用中不同租户的产品(请看多租户博客)。如果你的应用不是多租户,那么你不需要这个接口和属性。
获取一个组织单元中的实体
获取一个OU中的Products很简单,来看一下领域服务这个例子: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简单地写一个断言,如上所示。
获取一个包括子组织单元的组织单元的实体
我们可能想获取一个包括子组织单元的组织单元的Products。在这种情况下,OU Code(代码)可以帮到我们: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的Code。然后,我们创建了一个具有join和StartsWith(code)条件(在sql中StartsWith创建一个
Like查询)的LINQ。这样,我们就可以有层次低获得一个OU的products。
为用户过滤实体
我们可能获取在OU中的一个特定用户的所有Products,看下面的样例代码: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,然后获取Products时使用了Contains条件。当然,我们可以创建一个具有join的LINQ查询来获得相同的列表。
我们可能想要获取包括子OU的用户OU的Products:
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(); } }
我们将具有
StartsWith条件的
Any联合到了一个LINQ join语句中。
当然,也可能有更复杂的需求,但是所有的需求都可以使用LINQ或SQL完成。
设置
你可以注入然后使用IOrganizationUnitSettings接口来获取OU的设置值。当前,只有一个你可以更改的设置:MaxUserMembershipCount:一个用户最大允许的关系数量。默认值是
int.MaxValue,它允许用户同时成为无限OU的成员。设置名称是一个定义在
AbpZeroSettingNames.OrganizationUnits.MaxUserMembershipCount中的常量。
你可以使用设置管理者修改设置值。
相关文章推荐
- 阅读《Android 从入门到精通》(16)——表状时钟
- C++对xml文档操作 CMarkUp
- 解决:信息中插入avi格式的视频时,提示“unsupported video format”
- Android Studio 上传本地代码至github
- Android Content Provider的启动过程源码分析
- (笔记)Mysql实例:建库建表并插入数据2
- NYOJ:题目56 阶乘因式分解(一)
- LeetCode WiggleSort I && II
- (笔记)Mysql实例:建库建表并插入数据1
- shell awk
- Struts2 配置文件result的name属性和type属性
- (笔记)Mysql命令mysqldump:备份数据库
- (笔记)Mysql命令rename:修改表名
- 评“解决了问题的同时,又制造了新问题”
- HDU 5612 Baby Ming and Matrix games(dfs搜索)
- (笔记)Mysql命令alter add:增加表的字段
- Codeforces Round #340 (Div. 2)-B. Chocolate(组合数学的乘法计数)
- Android快捷支付SDK Demo resultStatus={4001};memo={參数错误};result={}问题
- 我是怎样向别人提问题的?
- 矩阵和散列表