当前位置:   article > 正文

第十五篇_currentunitofwork.savechangesasync 报错

currentunitofwork.savechangesasync 报错

首页新闻博问专区闪存云上钜惠                          我的博客我的园子账号设置退出登录注册登录wuhuacong(伍华聪)的专栏 随笔 - 683, 文章 - 20, 评论 - 8152, 引用 - 20ABP框架中一对多,多对多关系的处理以及功能界面的处理(2) 在我们开发业务的时候,一般数据库表都有相关的关系,除了单独表外,一般还包括一对多、多对多等常见的关系,在实际开发过程中,需要结合系统框架做对应的处理,本篇随笔介绍基于ABP框架对EF实体、DTO关系的处理,以及提供对应的接口进行相关的数据保存更新操作,这篇介绍多对多关系下的ABP框架的处理。 在我们开发业务的时候,一般数据库表都有相关的关系,除了单独表外,一般还包括一对多、多对多等常见的关系,在实际开发过程中,需要结合系统框架做对应的处理,本篇随笔介绍基于ABP框架对EF实体、DTO关系的处理,以及提供对应的接口进行相关的数据保存更新操作,这篇介绍多对多关系下的ABP框架的处理。上篇随笔《ABP框架中一对多,多对多关系的处理以及功能界面的处理(1)》介绍了一对多关系下的主从表数据处理,包括ABP框架对EF实体、DTO等关系处理,以及应用层基类接口的调整和Apicaller调用层的封装,最后介绍了基于代码生成工具快速生成所需ABP框架代码和Winform界面代码的过程。本篇基于ABP框架的基础上,继续介绍多对多关系的数据库设计、框架代码生成和调整,以实现常见多对多关系的数据处理。1、多对多关系的数据库设计和界面关系一般多对多的关系是指两个业务表之间存在关联关系,它们通过中间表(包含两个表的外键关系)建立多对多的关系,ABP框架除了两个外键关系外,一般还会增加几个系统字段,如下所示。角色包含菜单资源也是多对多的关系,一般在角色新增或者编辑界面中进行维护。或者功能界面设计的时候,就需要考虑和这些表之间的关系维护,如商品类型中,基本信息里面和品牌关系进行绑定。不管上面的树形列表,还是很后面的复选框组,都是先请求关联主表的数据,然后再请求对应角色或者商品类型下的关系数据,绑定到界面上。如对于上面的树形列表,通过设置树列表的数据,以及选中的记录就可以实现对应关系的绑定。 因此,在树形列表绑定的时候,需要请求原有的全部菜单数据,以及属于该角色下的菜单数据,两相整合就可以实现复选框选中已有菜单的效果了。 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所示。    /// <summary>
/// 品牌简单信息
/// </summary>
public class BrandItemDto
{
    /// <summary>
    /// 品牌ID
    /// </summary>
    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方法。        /// <summary>
    /// 对记录进行转义
    /// </summary>
    /// <param name="item">dto数据对象</param>
    /// <returns></returns>
    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 信息集合
    }弄好了这些,我们测试接口,可以正确获得对应的记录列表了。这样我们就可以在列表或者编辑界面里都展示对应的关系了。在列表展示界面中绑定已有关系代码如下所示。  <el-table-column align="center" label="绑定品牌列表">
<template slot-scope="scope">
  <el-tag
    v-for="opt in scope.row.bindBrandItems"
    :key="opt.id"
    type="primary"
    :disable-transitions="false"
  >
    {{ opt.brandName }}
  </el-tag>
</template>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

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

{{ 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 就是修改已有的品牌关系,在介绍这个函数开始前,先来看看商品类型应用服务层的定义,引入了商品类型、品牌、商品类型和品牌关系表三者的仓储对象作为参数的。    /// <summary>
/// 商品类型,应用层服务接口实现
/// </summary>
[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 需要修改关系,那么它的逻辑就是:如果不在新列表中的,移除数据库中的关系;如果新列表记录已在数据库中存在则跳过,否则写入关系。详细代码如下所示,这个也是我们处理中间表之间关系的常见处理逻辑了。        /// <summary>
    /// 添加品牌到分类
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    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));
                }
            }
        }
    }这样我们在商品类型编辑界面中可以随时变更关联关系了。以上就是关于中间表的常见处理操作,希望对你学习ABP框架或者Element前端界面有所帮助。  为了方便读者理解,我列出一下前面几篇随笔的连接,供参考:循序渐进VUE+Element 前端应用开发(1)--- 开发环境的准备工作循序渐进VUE+Element 前端应用开发(2)--- Vuex中的API、Store和View的使用循序渐进VUE+Element 前端应用开发(3)--- 动态菜单和路由的关联处理循序渐进VUE+Element 前端应用开发(4)--- 获取后端数据及产品信息页面的处理循序渐进VUE+Element 前端应用开发(5)--- 表格列表页面的查询,列表展示和字段转义处理循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用循序渐进VUE+Element 前端应用开发(7)--- 介绍一些常规的JS处理函数循序渐进VUE+Element 前端应用开发(8)--- 树列表组件的使用循序渐进VUE+Element 前端应用开发(9)--- 界面语言国际化的处理循序渐进VUE+Element 前端应用开发(10)--- 基于vue-echarts处理各种图表展示 循序渐进VUE+Element 前端应用开发(11)--- 图标的维护和使用循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理循序渐进VUE+Element 前端应用开发(14)--- 根据ABP后端接口实现前端界面展示循序渐进VUE+Element 前端应用开发(15)--- 用户管理模块的处理循序渐进VUE+Element 前端应用开发(16)--- 组织机构和角色管理模块的处理 循序渐进VUE+Element 前端应用开发(17)--- 菜单管理循序渐进VUE+Element 前端应用开发(18)--- 功能点管理及权限控制  循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码  循序渐进VUE+Element 前端应用开发(21)--- 省市区县联动处理的组件使用循序渐进VUE+Element 前端应用开发(22)--- 简化main.js处理代码,抽取过滤器、全局界面函数、组件注册等处理逻辑到不同的文件中 循序渐进VUE+Element 前端应用开发(23)--- 基于ABP实现前后端的附件上传,图片或者附件展示管理循序渐进VUE+Element 前端应用开发(24)--- 修改密码的前端界面和ABP后端设置处理 循序渐进VUE+Element 前端应用开发(25)--- 各种界面组件的使用(1)循序渐进VUE+Element 前端应用开发(26)--- 各种界面组件的使用(2) ABP框架中一对多,多对多关系的处理以及功能界面的处理(1) 电商商品数据库的设计和功能界面的处理  ABP框架中一对多,多对多关系的处理以及功能界面的处理(2) 主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发
		专注于Winform开发框架/混合式开发框架、Web开发框架、Bootstrap开发框架、微信门户开发框架的研究及应用。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

转载请注明出处:
撰写人:伍华聪  http://www.iqidi.com 
     标签: ABP框架使用好文要顶 关注我 收藏该文 伍华聪
关注 - 82
粉丝 - 8637 +加关注 2 1

« 上一篇: 电商商品数据库的设计和功能界面的处理 posted on 2020-11-12 10:22  伍华聪  阅读(314)  评论(0)  编辑  收藏

刷新评论刷新页面返回顶部

发表评论 【福利】注册AWS账号,立享12个月免费套餐 编辑预览 7693b08a-a8f6-49f3-f45a-08d88556cc23 Markdown 帮助自动补全 不改了退出 订阅评论 [Ctrl+Enter快捷键提交]

首页 新闻 博问 专区 闪存 班级 【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】博客园 & 陌上花开HIMMR 给单身的程序员小哥哥助力脱单啦~
【推荐】博客园 & 示说网联合策划,AI实战系列公开课第二期
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【福利】AWS携手博客园为开发者送免费套餐与抵扣券
【推荐】 阿里云折扣价格返场,错过再等一年
最新 IT 新闻:
· 拼多多财报电话会议实录:多多买菜并非社区拼团购物
· 久经沙场的战士对决:张小龙大战张一鸣
· 双十一吐槽:异化与集体无意识
· 小鹏汽车上市后首份财报:营收19亿 首度实现毛利转正
· 腾讯第三季度总收入为1254.47亿元 同比增长29%
» 更多新闻… 历史上的今天:
2015-11-12 如何在Winform界面中设计图文并茂的界面
2013-11-12 利用代码生成工具Database2Sharp设计数据编辑界面
2009-11-12 关于MSHTML控件使用的问题

导航博客园 首页 新随笔 联系 订阅 管理 < 2020年11月> 日一二三四五六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1 2 3 4 5 6 7 8 9 10 11 12

公告 昵称: 伍华聪
园龄: 15年4个月
粉丝: 8637
关注: 82 +加关注

搜索  常用链接 我的随笔我的评论我的参与最新评论我的标签最新随笔1.ABP框架中一对多,多对多关系的处理以及功能界面的处理(2) 2.电商商品数据库的设计和功能界面的处理 3.ABP框架中一对多,多对多关系的处理以及功能界面的处理(1) 4.循序渐进VUE+Element 前端应用开发(26)— 各种界面组件的使用(2) 5.循序渐进VUE+Element 前端应用开发(25)— 各种界面组件的使用(1) 6.循序渐进VUE+Element 前端应用开发(24)— 修改密码的前端界面和ABP后端设置处理 7.循序渐进VUE+Element 前端应用开发(23)— 基于ABP实现前后端的附件上传,图片或者附件展示管理 8.循序渐进VUE+Element 前端应用开发(22)— 简化main.js处理代码,抽取过滤器、全局界面函数、组件注册等处理逻辑到不同的文件中 9.循序渐进VUE+Element 前端应用开发(21)— 省市区县联动处理的组件使用 10.在Winform程序中使用Spire.Pdf实现页面添加印章处理 我的标签Winform开发框架(168) WinForm界面开发(82) 开发辅助(78) 微信公众平台及门户应用(76) Web开发框架(49) Bootstrap开发框架(47) 代码生成工具(38) 共享软件开发交流(38) 循序渐进VUE+Element(29) ABP框架使用(26) 更多 积分与排名 积分 - 2058350 排名 - 42 随笔档案 (683) 2020年11月(5) 2020年10月(4) 2020年9月(5) 2020年8月(1) 2020年7月(7) 2020年6月(9) 2020年5月(4) 2020年4月(3) 2020年3月(5) 2020年1月(3) 2019年12月(2) 2019年11月(4) 2019年10月(8) 2019年9月(1) 2019年7月(6) 2019年6月(8) 2019年5月(5) 2019年4月(3) 2019年3月(5) 2019年2月(7) 文章分类 (19) 开发的共享软件(19) 我的好友 黎波(Blogs) 吉日嘎拉 Winform开发框架 我的简书博客 张善友 我的技术支持站点 广州爱奇迪 Database2Sharp下载 简书博客 最新评论1. Re:电商商品数据库的设计和功能界面的处理666–滴答的雨2. Re:电商商品数据库的设计和功能界面的处理感谢分享–WebAssembly3. Re:使用.net core3.0 正式版创建Winform程序core的窗体设计器还很残废,比如tab键序就不可用,还有拖拉体验糟糕,感觉卡。 空窗体生成的exe也比较大,还带个同名dll,请教怎么不生成这个dll? 总之感觉不好…–ahdung4. Re:电商商品数据库的设计和功能界面的处理楼主有没有订单,支付,这块的设计方案可以参考下–最爱晴天5. Re:电商商品数据库的设计和功能界面的处理感谢分享~~~–墨墨墨墨小宇阅读排行榜 1. DevExpress控件使用经验总结(229703) 2. 基于MVC4+EasyUI的Web开发框架形成之旅–界面控件的使用(223139) 3. 基于Metronic的Bootstrap开发框架经验总结(5)–Bootstrap文件上传插件File Input的使用(211444) 4. 基于Metronic的Bootstrap开发框架经验总结(16)-- 使用插件bootstrap-table实现表格记录的查询、分页、排序等处理(197499) 5. 合理的布局,绚丽的样式,谈谈Winform程序的界面设计(174147) 6. Winform开发框架主界面设计展示(146707) 7. Web API接口设计经验总结(129690) 8. 基于Metronic的Bootstrap开发框架经验总结(1)-框架总览及菜单模块的处理(127315) 9. 基于Metronic的Bootstrap开发框架经验总结(3)–下拉列表Select2插件的使用(125915) 10. C#开发微信门户及应用(1)–开始使用微信接口(118473) 评论排行榜 1. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(4)----CSV、Excel、INI文件、独立存储等文件相关(201) 2. 基于MVC4+EasyUI的Web开发框架形成之旅–界面控件的使用(186) 3. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)----开篇总结(176) 4. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(12)— 网络相关操作辅助类(123) 5. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(14)—Winform开发的常用类库(终结篇,CHM文档放送)(102) 推荐排行榜 1. C#开发微信门户及应用(1)–开始使用微信接口(77) 2. 基于MVC4+EasyUI的Web开发框架形成之旅–界面控件的使用(70) 3. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)----开篇总结(66) 4. C#开发微信门户及应用(19)-微信企业号的消息发送(文本、图片、文件、语音、视频、图文消息等)(52) 5. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(14)—Winform开发的常用类库(终结篇,CHM文档放送)(44)

Powered by: 	 
  • 1

博客园
Copyright © 2020 伍华聪
Powered by .NET 5.0.0 on Kubernetes

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/135960
推荐阅读
相关标签
  

闽ICP备14008679号