转载

Module-Zero之组织单元(OU)管理【新增】

返回《Module Zero学习目录》

  • 概览介绍
  • 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 中的常量。

你可以使用 设置管理者 修改设置值。

原文  http://www.cnblogs.com/farb/p/modulezeroOrganizationUnitManagement.html
正文到此结束
Loading...