不管上面的树形列表,还是很后面的复选框组,都是先请求关联主表的数据,然后再请求对应角色或者商品类型下的关系数据,绑定到界面上。

如对于上面的树形列表,通过设置树列表的数据,以及选中的记录就可以实现对应关系的绑定。

复制代码

复制代码
因此,在树形列表绑定的时候,需要请求原有的全部菜单数据,以及属于该角色下的菜单数据,两相整合就可以实现复选框选中已有菜单的效果了。

复制代码
async getlist() { // 树列表数据获取
// 获取全部功能列表
var param = { SkipCount: 0, MaxResultCount: 1000, Tag: ‘web’ }
var treeList = [] // 所有功能列表
await menu.GetAll(param).then(data => {
treeList = data.result.items
})
// console.log(treeList)

  // 获取角色菜单列表var grantedList = []if (this.roleId && typeof (this.roleId) !== 'undefined') {param = { RoleId: this.roleId, MaxResultCount: 1000, MenuTag: 'web' }await role.GetMenusInRole(param).then(data => {grantedList = data.result.items})}// console.log(grantedList)

复制代码

当然我们也可以把角色包含菜单数据放在角色对象的DTO里面,然后一次性就可以获得菜单集合了,如我这里介绍的商品类型中的包含的品牌列表做法一样。

2、ABP后端对于多对多关系的处理
多对多关系,是我们业务表常见的一种关系,如果是只读的展示,我们直接通过关联关系获得记录展示即可;如果是进行编辑的处理,那么需要获取关联主表的全部记录进行展示,然后根据关联关系,显示复选框勾中的记录展示。

刚才说到,我们商品类型中对于多对多的关系,可以通过后端直接返回对应的数据记录集合的,这种做法可以避免细粒度API的请求过程,不过对于太大的数据集合,建议还是通过单独的API进行获取。

我们为了在商品类型中返回相关品牌信息,那么需要定义一个简单的对象用来承载品牌信息,如下DTO所示。

复制代码
///
/// 品牌简单信息
///
public class BrandItemDto
{
///
/// 品牌ID
///
public virtual long Id { get; set; }

    /// <summary>/// 品牌编码/// </summary>public virtual string BrandCode { get; set; }/// <summary>/// 品牌名称/// </summary>public virtual string BrandName { get; set; }
}

复制代码
这个DTO是我们自定义的,我们需要映射常规的品牌DTO对象到这个自定义的DTO里面,那么我们可以通过映射文件中加入对应的映射关系来处理,避免属性的一一复制,如下所示。

然后,就是我们在商品类型中使用这个DTO的集合了,如下所示。

我们知道,我们所有业务对象提供服务,都是通过对应的应用层服务接口提供,而商品类型这里对应的应用服务层对象是ProductTypeAppService,它继承自MyAsyncServiceBase基类对象,MyAsyncServiceBase基类对象重写了一些常规的方法,以便提供更方便的服务接口。

其中为了数据对象的转换方便,我们重写了Get和GetAll的方法,并提供一个通用的模板方法用来修改对象DTO的关系,如下代码所示。

其中ConvertDto方法就是我们给子类重写,以便实现数据转换关系的。例如,我们在子类ProductTypeAppService里面重写了ConvertDto方法。

复制代码
///
/// 对记录进行转义
///
/// dto数据对象
///
protected override void ConvertDto(ProductTypeDto item)
{
//重写ConvertDto方法,返回其他关系数据
var bindedBrands = GetBindedBrands(item.Id).Result.Items;
//获取关联品牌的ID列表
var brandIds = bindedBrands.Select(s => s.Id).ToArray();

        //获取关联品牌的对象列表var brandDtos = bindedBrands.Select(ObjectMapper.Map<BrandItemDto>).ToList();item.BindBrands = brandIds;     //纯ID集合item.BindBrandItems = brandDtos;//ID,BrandName,BrandCode 信息集合}

复制代码
弄好了这些,我们测试接口,可以正确获得对应的记录列表了。

这样我们就可以在列表或者编辑界面里都展示对应的关系了。

在列表展示界面中绑定已有关系代码如下所示。

复制代码

{{ opt.brandName }}

复制代码
在编辑界面中绑定已有关系代码如下所示。

复制代码

{{ item.brandName }}

复制代码
其中editForm.bindBrands是我们包含的关系,而brandList这是所有品牌列表,这个需要在页面创建的时候,单独获取。

最后,需要介绍一下数据提交的时候,我们需要根据绑定列表关系,修改数据库已有的关联记录,这样实现关联关系的更新。

我们来看看创建商品类型和更新商品类型的时候,对关系数据的处理。

复制代码
///
/// 重写创建操作,写入额外的信息
///
/// 商品类型对象DTO
///
public override async Task CreateAsync(CreateProductTypeDto input)
{
CheckCreatePermission();
var entity = MapToEntity(input);

        await Repository.InsertAsync(entity);await CurrentUnitOfWork.SaveChangesAsync();//写入中间表关系if (input.BindBrands != null){foreach (var brandId in input.BindBrands){//增加新增的await _brandTypeRepository.InsertAsync(new BrandType(AbpSession.TenantId, brandId, entity.Id));}}return MapToEntityDto(entity);}/// <summary>/// 重写更新操作,更新新的关系数据/// </summary>/// <param name="input">商品类型对象DTO</param>/// <returns></returns>public override async Task<ProductTypeDto> UpdateAsync(ProductTypeDto input){//保存主记录var dto = await base.UpdateAsync(input);//写入中间表关系if (input.BindBrands != null){var brandsDto = new BrandsToProductTypeDto() { BrandIds = input.BindBrands, ProductTypeId = input.Id };await AddBrandToType(brandsDto);}return dto;}

复制代码
其中 AddBrandToType 就是修改已有的品牌关系,在介绍这个函数开始前,先来看看商品类型应用服务层的定义,引入了商品类型、品牌、商品类型和品牌关系表三者的仓储对象作为参数的。

复制代码
///
/// 商品类型,应用层服务接口实现
///
[AbpAuthorize]
public class ProductTypeAppService : MyAsyncServiceBase<ProductType, ProductTypeDto, long, ProductTypePagedDto, CreateProductTypeDto, ProductTypeDto>, IProductTypeAppService
{
private readonly IRepository<ProductType, long> _repository;//业务对象仓储对象
private readonly IRepository<User, long> _userRepository;//用户信息仓储对象
private readonly IRepository<BrandType, long> _brandTypeRepository;//品牌分类中间表对象仓储对象
private readonly IRepository<Brand, long> _brandRepository;//业务对象仓储对象

    public ProductTypeAppService(IRepository<ProductType, long> repository, IRepository<BrandType, long> brandTypeRepository, IRepository<Brand, long> brandRepository, IRepository<User, long> userRepository) : base(repository){_repository = repository;_brandTypeRepository = brandTypeRepository;_brandRepository = brandRepository;_userRepository = userRepository;}

复制代码
其中 AddBrandToType 需要修改关系,那么它的逻辑就是:如果不在新列表中的,移除数据库中的关系;如果新列表记录已在数据库中存在则跳过,否则写入关系。

详细代码如下所示,这个也是我们处理中间表之间关系的常见处理逻辑了。

复制代码
///
/// 添加品牌到分类
///
///
///
public async Task AddBrandToType(BrandsToProductTypeDto input)
{
var typeInfo = Repository.GetAsync(input.ProductTypeId);
if (typeInfo != null)
{
//获取与中间表联合的查询表达式
var query = from cb in _brandTypeRepository.GetAll()
join b in _brandRepository.GetAll() on cb.Brand_ID equals b.Id
where cb.ProductType_ID == input.ProductTypeId
select b;

            var oldNotInNewList = query.Where(p => !input.BrandIds.Contains(p.Id)).ToList();foreach (var info in oldNotInNewList){//移除已有,但不在添加列表中的await _brandTypeRepository.DeleteAsync(m => m.ProductType_ID == input.ProductTypeId && m.Brand_ID == info.Id);}if (input.BrandIds != null){//获取已有绑定列表var currentBrands = query.ToList();foreach (var brandid in input.BrandIds){if (currentBrands.Any(cr => cr.Id == brandid)){continue; //已有重复的跳过}//否则增加新增的await _brandTypeRepository.InsertAsync(new BrandType(AbpSession.TenantId, brandid, input.ProductTypeId));}}}}亚马逊测评 www.yisuping.com

ABP框架中一对多,多对多关系的处理以及功能界面的处理(2)相关推荐

  1. SQLAlchemy_定义(一对一/一对多/多对多)关系

    SQLAlchemy_定义(一对一/一对多/多对多)关系 目录 Basic Relationship Patterns One To Many One To One Many To Many Basi ...

  2. AutoMapper在ABP框架中的使用说明

    为了说明AutoMapper如何使用,我专门开设了一个专题来讲,如果您还没有查看该专题,请点击这里.既然系统地学习了AutoMapper,那么接下来就是该用它实战的时候了.今天,我们就来揭开AutoM ...

  3. ABP 详解系列2:解析ABP框架中的数据传输对象与应用服务

    解析ABP框架中的数据传输对象与应用服务 ABP框架是基于ASP.NET的Web开发框架,在ABP中应用服务将领域逻辑暴露给展现层,展现层通过传入数据传输对象参数来调用应用服务,而这里我们就来解析AB ...

  4. Hibernate一对多/多对一关系映射详解及相应的增删查改操作

    以客户与订单的关系为例 1.在实体模型类中绑定两者关系: 客户类: public class Customer {private Integer id;//客户idprivate String nam ...

  5. abp.ajax get,ABP框架中导航菜单的使用及JavaScript API获取菜单的方法

    每一个WEB应用程序都有导航菜单,Abp也为用户提供了通用的创建和显示菜单方式. 创建菜单一个应用程序可能包含不同的模块,而每个模块都可能有它自己的菜单项.在Abp中,需要创建一个派生自Navigat ...

  6. 数据库一对一 一对多 多对多关系

    参考:https://blog.csdn.net/u013144287/article/details/79024130 自己在项目中写的实例: '实体'和'公理'具有多对多关系,即一个实体可以对应多 ...

  7. 数据库外键:一对多/多对多关系

    数据库事务四大特性ACID: 原子性(Atomicity) 一致性(Consistency) 隔离性(Isolation) 持久性(Durability) 基于原子性对存在重复数据的表进行拆分 一对多 ...

  8. sql中一对多,多对一,一对一关系的解析

    1.一对多:比如说一个班级有很多学生,可是这个班级只有一个班主任.在这个班级中随便找一个人,就会知道他们的班主任是谁:知道了这个班主任就会知道有哪几个学生.这里班主任和学生的关系就是一对多. 2.多对 ...

  9. hibernate 一对多 多对一 关系表 增删改查大礼包ps二级查也有

    今天来到混元气功 这货大概的意思就是你中有我 我中有你 ps 这里就要说到维护关系 ps写这个用了我一下午--.也是刚刚好复习到这里 顺便就写写 注意:一般都在多方维护关系,至于是用单向还是用多向要看 ...

最新文章

  1. 逻辑回归原理(python代码实现)
  2. 重复数据删除将成标配功能
  3. firefox addons
  4. Ubuntu学习日记--Lesson9:显卡工作状态查看命令
  5. HTML请选择编程,html – 设计选择标记
  6. 在vs2005调试asp程序
  7. BMW Trojan 样本分析
  8. 2006技术盘点 多项无线技术被高估
  9. 读《如何阅读一本书》乱摘
  10. matlab卡住了 打不开,win7系统matlab打不开无法运行的解决方法
  11. 告别360全家桶,安利一波电脑必备软件
  12. 大一计算机课总结400字,第一学月总结400字以上
  13. 统计天数oracle,Oracle计算连续天数,计算连续时间,Oracle连续天数统计
  14. oracle fnd_global,Oracle Report(Report 6i/RDF)使用全局变量fnd_global, fnd_frofile
  15. mysql Events及存储过程查看
  16. 美团王兴,为什么让骑手注册个体户?详解他的套路,望周知
  17. 【拓展】腾讯十大最受欢迎的开源项目!
  18. C++11绑定器bind及function机制
  19. 消防气体灭火系统(二)
  20. Linux:chmod命令

热门文章

  1. python虚拟环境是什么意思_Python虚拟环境详解
  2. Vue前端浏览器链接/接口参数实现加密
  3. 当前地址栏(URL)参数含有特殊符号的处理[vue]
  4. Learn Golang
  5. docker容器重启
  6. 经典北京话语录~~~~
  7. 快用苹果助手安装失败_为什么我的苹果ID总是说ID或密码不对!我输入的是正确的!...
  8. nashorn_Nashorn简介
  9. 第三届云计算大会 - Dell云计算: 企业的有效转型策略(转载)
  10. 神雕侠侣手游答疑大全