组织单位

介绍

组织单位(OU)可用于对用户和实体进行分层分组。

OrganizationUnit实体

OU由OrganizationUnit实体表示。该实体的基本属性是:

OrganizationUnit实体的主键(Id)是long类型,它派生自  FullAuditedEntity  类,它提供审计信息并实现  ISoftDelete  接口(OU不会从数据库中删除,它们只是标记为已删除)。

组织树

由于OU可以具有父级,因此租户的所有OU都是树结构。这棵树有一些规则;

OU代码

OU代码由OrganizationUnit Manager自动生成和维护。这是一个看起来像这样的字符串:

“00001.00042.00005”

此代码可用于轻松查询OU的所有子项的数据库(递归)。这段代码有一些规则:

OrganizationUnit Manager

可以注入 OrganizationUnitManager类   并用于管理OU。常见用例是:

多租户

OrganizationUnitManager旨在一次为单个租户工作。它适用于当前租户的默认值。

常见用例

在这里,我们将看到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接口,它具有可为空的OrganizationUnitId属性。

我们现在可以将产品与OU相关联并查询特定OU的产品。

请注意; 产品实体必须具有TenantId(IMustHaveTenant的属性),以便将其与多租户应用程序中的不同租户的产品区分开来(请参阅组织单位中的  获取实体)

获取OU的产品很简单。我们来看看这个示例  域服务

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编写谓词。

获取包含其子组织单位的组织单位中的实体

我们可能希望获得组织单位的产品,包括儿童组织单位。在这种情况下,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中的所有产品。示例代码:

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条件。我们也可以使用join创建一个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();
    }
}

我们将Any与StartsWith条件组合成一个LINQ连接语句。

很可能会有更复杂的需求,但它们都可以通过LINQ或SQL完成。

设置

您可以注入并使用IOrganizationUnitSettings接口来获取组织单位的设置值。目前只有一个设置可以根据您的应用需求进行更改:

您可以使用设置管理器更改设置值  

nidie.com.cn - 用心与你沟通