182  
查询码:00000040
涉及ABP中UnitOfWork遇到的问题
作者: 陈一奇 于 2022年01月24日 发布在分类 / 人防组 / 人防后端 下,并于 2022年01月24日 编辑
UnitOfWork

1. “Cannot access a disposed object. A common cause of this error is disposing”异常分析

知识点:

在ABP框架中,AppService 等是自带UnitOfWork的。然后其他的例如  后台任务(BackgroundWork)、定时任务(AbpQuartz)等的Excute方法没有自带UnitOfWork特性。
UnitOfWork(工作单元):
工作单元在ABP承担着 数据库链接以及事务的责则,同一个工作单元中共享一个数据库连接以及事务。
问题解析:
异常中描述的就是数据库上下文  DBContext 被释放了。那么为什么被释放了?其实就是翻译问题。真实的情况是  就是DBContext还没有打开数据库链接。
我们从官方文档对UnitOfWork的介绍中(文档链接在下面),对于GetAll()方法的调用前需要先打开数据库链接(详细原因的请看文档介绍)。

粘贴图片
首先的方法中没有定义UnitOfWork(工作单元),由于工作单元在Abp中负责数据库的链接以及事务,导致方法执行时没有打开数据库链接,在执行IRepository.GetAll方法时,由于GetAll方法需要提前打开数据库链接,所以抛出了DBContext已经被释放的异常。

解决方案:
在GetAll执行前打开数据库链接。既然UnitOfWork负责链接和事务,那么就在方法上添加[UnitOfWork]特性就可以了。

官方文档:

https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work#irepository-getall-method

2._unitOfWorkManager.Current.SaveChanges() 失效

这里,我想实现的是,在方法执行完之前将数据先入库,使用了_unitOfWorkManager.Current.SaveChanges();似乎没有效果,不知道是否和同步异步有啥关系,后来查了一下,方法上面加上  [UnitOfWork(false)]这个属性就好了,目前还不知道是啥原因。贴上源码有知道的大佬麻烦帮我看一下

/// <summary>
        /// 新增
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [UnitOfWork(false)]
        public async Task<MaintenancePlanAndRuleDetailDto> CreateMaintenancePlan(MaintenancePlanAndRuleCreateDto input)
        {
            string token = _httpContextAccessor.HttpContext.Request.Headers["token"];
           
            MaintenancePlanAndRuleDetailDto result = new MaintenancePlanAndRuleDetailDto();
            List<MaintenanceRuleDetailDto> ruleDetailList = new List<MaintenanceRuleDetailDto>();
            MaintenancePlanRuleCreateDto perRuleDetail = new MaintenancePlanRuleCreateDto();

            List<string> ruleRowGuid = input.RuleRowGuids;
            MaintenancePlanCreateDto planCreate = new MaintenancePlanCreateDto();
            MaintenancePlanDetailDto planDetail = new MaintenancePlanDetailDto();

            planCreate = new MaintenancePlanCreateDto();
            planCreate.SystemName = input.SystemName;
            planCreate.EquipmentRowGuid = input.EquipmentRowGuid;
            planCreate.MaintancePeople = input.MaintancePeople;
            planCreate.IsEnable = input.IsEnable;
            planCreate.StartDate = input.StartDate;
            planCreate.EndDate = input.EndDate;
            planCreate.Creater = input.Creater;
           
           var codeDtoStatus = (await _codeItemsAPIService.GetCodeMainByCode("EventStatus", token)).ToObject<ResponseCodeItemDto>().Result;
            foreach (var code1 in codeDtoStatus)
            {
                if (code1.Label == "未开始")
                {
                    planCreate.Status = code1.Value;
                    break;
                }
            }

            planDetail = _objectMapper.Map<MaintenancePlanDetailDto>(_repository.Insert(_objectMapper.Map<Maintenance_Plan>(planCreate)));
           
            if (ruleRowGuid != null && ruleRowGuid.Count>0) {
                Maintenance_Rule ruleDB = _maintenanceRuleRepository.GetAllList().Where(e => e.Id == ruleRowGuid.FirstOrDefault()).FirstOrDefault();
                var codeDtoone = (await _codeItemsAPIService.GetCodeMainByCode("System", token)).ToObject<ResponseCodeItemDto>().Result;
                string systemName = "";
                foreach (var code1 in codeDtoone)
                {
                    if (ruleDB.SystemName == code1.Value)
                    {
                        systemName = code1.Label;
                        break;
                    }

                }
                var equipmentDB = _archvieEquipmentRepository.GetAllList().Where(e => e.Id == ruleDB.EquipmentName).FirstOrDefault();
                ruleDetailList = _objectMapper.Map<List<MaintenanceRuleDetailDto>>(_maintenanceRuleRepository.GetAllList().Where(e => e.SystemName == ruleDB.SystemName && e.EquipmentName == ruleDB.EquipmentName));
                foreach (var perRuleDetailDB in ruleDetailList) {
                    perRuleDetailDB.Select = false;
                }
                //result.SystemRuleLabel = systemName + "," + equipmentDB.EquipmentName;
                result.SystemRuleLabel = systemName + "," + ruleDB.EquipmentName;
            }

            foreach (var perRuleId in ruleRowGuid)
            {
           
                perRuleDetail.PlanRowGuid = planDetail.Id;
                perRuleDetail.RuleRowGuid = perRuleId;
                Maintenance_PlanRule planRule= _maintenancePlanRuleRepository.Insert(_objectMapper.Map<Maintenance_PlanRule>(perRuleDetail));
                _unitOfWorkManager.Current.SaveChanges();
                //如果启用,创建定时job
                if (input.IsEnable.Value)
                {
                    var rule = _maintenanceRuleRepository.GetAll().Where(e => e.Id == perRuleId).FirstOrDefault();

                    var codeDtoone = (await _codeItemsAPIService.GetCodeMainByCode("MaintainType", token)).ToObject<ResponseCodeItemDto>().Result;
                    string type = "";
                    foreach (var code1 in codeDtoone)
                    {
                        if (rule.MaintainType == code1.Value)
                        {
                            type = code1.Label;
                            break;
                        }

                    }
                    var codeDtotwo = (await _codeItemsAPIService.GetCodeMainByCode("Cycle", token)).ToObject<ResponseCodeItemDto>().Result;
                    string unitName = "";
                    foreach (var code2 in codeDtotwo)
                    {
                        if (rule.TimeUnit == code2.Value)
                        {
                            unitName = code2.Label;
                            break;
                        }

                    }
                    await _jobService.ScheduleJobByPlan(planRule.Id, input.StartDate.Value, input.EndDate.Value, type, unitName, rule.Cycle.Value, true);
                    }
                    foreach (var perPlanRule in ruleDetailList) {
                    if (perPlanRule.Id == perRuleId) {
                        perPlanRule.Select = true;
                    }
                }
            }
           
            result.SystemName = planDetail.SystemName;
            var equipDB = _archvieEquipmentRepository.GetAllList().Where(e => e.Id == planDetail.EquipmentRowGuid).FirstOrDefault();
            if (equipDB != null)
            {
                result.EquipmentName = equipDB.EquipmentName;
            }
            result.EquipmentRowGuid = planDetail.EquipmentRowGuid;
            result.MaintancePeople = planDetail.MaintancePeople;
       
            result.IsEnable = planDetail.IsEnable;
            result.StartDate = planDetail.StartDate;
            result.EndDate = planDetail.EndDate;
            result.Creater = planDetail.Creater;
            result.ruleDetail = ruleDetailList;
            result.Id = planDetail.Id;

            return await Task.FromResult(result);
        }



 推荐知识

 历史版本

修改日期 修改人 备注
2022-01-24 10:58:39[当前版本] 陈一奇 创建版本

 附件

附件类型

PNGPNG

知识分享平台 -V 4.8.7 -wcp