ABP Zero框架中应用Many-To-Many关系

ABP Zero最新版本的数据处理层已经升级为EF Core,因为EF 5.0已经支持Many-to-Many关系的定义。因此可以通过对实体类的定义添加“Many-To-Many”关系。

 

  1. 定义实体类Service。
    public class Service : Entity<Guid>, IMustHaveTenant
        {
            public int TenantId { get; set; }
    
            [Required]
            [StringLength(ServiceConsts.MaxServiceNameLength, MinimumLength = ServiceConsts.MinServiceNameLength)]
            public virtual string ServiceName { get; set; }
    
            [Required]
            [StringLength(ServiceConsts.MaxDescriptionLength, MinimumLength = ServiceConsts.MinDescriptionLength)]
            public virtual string Description { get; set; }
    
            public virtual DateTime EffectiveDate { get; set; }
    
            public virtual DateTime EndDate { get; set; }
    
            public virtual decimal BaseAmount { get; set; }
    
            public virtual bool BaseOnPerUnits { get; set; }
    
            public virtual bool CombineBaseRate { get; set; }
    
            public virtual bool LadderType { get; set; }
    
            [Required]
            public virtual string CalculationMethod { get; set; }
            public virtual ICollection<Tax> Taxes { get; set; }
    
            public Service()
            {
                this.Taxes = new HashSet<Tax>();
            }
        }

     

  2. 定义实体类Tax。
    public class Tax : FullAuditedEntity<Guid>, IMustHaveTenant
        {
            public int TenantId { get; set; }
    
            [Required]
            [StringLength(TaxConsts.MaxCodeLength, MinimumLength = TaxConsts.MinCodeLength)]
            public virtual string Code { get; set; }
    
            [Required]
            public virtual Guid RevenueCodeId { get; set; }
            
            [ForeignKey("RevenueCodeId")]
            public RevenueCode RevenueCodeFk { get; set; }
    
            [Required]
            [StringLength(TaxConsts.MaxDescriptionLength, MinimumLength = TaxConsts.MinDescriptionLength)]
            public virtual string Description { get; set; }
    
            public virtual decimal Percent { get; set; }
    
            public virtual decimal FlatAmount { get; set; }
    
            public virtual decimal? LowerLimit { get; set; }
    
            public virtual decimal? UpperLimit { get; set; }
    
            [Required]
            [StringLength(TaxConsts.MaxCalcMethodLength, MinimumLength = TaxConsts.MinCalcMethodLength)]
            public virtual string CalcMethod { get; set; }
    
            public virtual bool ApplytoAllCharges { get; set; }
            public virtual ICollection<Service> Services { get; set; }
    
            protected Tax()
            {
                this.Services = new HashSet<Service>();
            }
        }

     Many-To-Many关系在EF 5.0中实体类定义就是在实体类中定义与其有关系的类集合,即可。

  3. 修改CreateOrEditServiceDto对象,这个对象的作用主要是在业务层与领域层之间传递实体数据。
        public class CreateOrEditServiceDto : EntityDto<Guid?>
        {
            [Required]
            [StringLength(ServiceConsts.MaxServiceNameLength, MinimumLength = ServiceConsts.MinServiceNameLength)]
            public string ServiceName { get; set; }
    
            [Required]
            [StringLength(ServiceConsts.MaxDescriptionLength, MinimumLength = ServiceConsts.MinDescriptionLength)]
            public string Description { get; set; }
    
            public DateTime EffectiveDate { get; set; }
    
            public DateTime EndDate { get; set; }
    
            public decimal BaseAmount { get; set; }
    
            public bool BaseOnPerUnits { get; set; }
    
            public bool CombineBaseRate { get; set; }
    
            public bool LadderType { get; set; }
    
            [Required]
            public string CalculationMethod { get; set; }
    
            public List<NameValueDto<string>> TaxItems { get; set; }
        }

    增加了用于显示自身对应的Many-To-Many关系实体对象信息集合。在此处只给Service编辑Dto对象的代码,实际上在CreateOrEditTaxDto对象中也需要定义“public List<NameValueDto<string>> ServiceItems { get; set; }”属性。用于传递之前的关系。

  4. 修改ServicesAppService.cs文件中的数据保存方法,增加对Tax对象关系的保存。
      protected virtual async Task Create(CreateOrEditServiceDto input)
            {
                var service = ObjectMapper.Map<Service>(input);
    
                if (AbpSession.TenantId != null)
                {
                    service.TenantId = (int)AbpSession.TenantId;
                }
    
                foreach (var item in input.TaxItems)
                {
                    var tax = await _taxesRepository.FirstOrDefaultAsync(Guid.Parse(item.Value));
    
                    if (tax != null)
                    {
                        if (!service.Taxes.Contains(tax)) service.Taxes.Add(tax);
                    }
                }
    
                await _serviceRepository.InsertAsync(service);
    
            }
    
    protected virtual async Task Update(CreateOrEditServiceDto input)
            {
                var service = await _serviceRepository.GetAllIncluding(t => t.Taxes).FirstOrDefaultAsync(s => s.Id == input.Id);
    
                ObjectMapper.Map(input, service);
    
                service.Taxes.Clear();
    
                foreach (var item in input.TaxItems)
                {
                    var tax = await _taxesRepository.FirstOrDefaultAsync(Guid.Parse(item.Value));
    
                    if (tax != null)
                    {
                        if (!service.Taxes.Contains(tax)) service.Taxes.Add(tax);
                    }
                }
            }

    Create与Update方法的区别是,Create方法需要主动调用Repository对象的Insert方法,而Update就去并不需要主动调用Repository对象的Update方法。

  5.   修改GetServiceForEditOutput类,这个类的作用主要是在业务层与表示层之彰传递实体数据。

        public class GetServiceForEditOutput
        {
            public CreateOrEditServiceDto Service { get; set; }
            public List<ComboboxItemDto> TaxeItems { get; set; }
    
            public GetServiceForEditOutput()
            {
                TaxeItems = new List<ComboboxItemDto>();
            }
        }
  6. 修改CreateOrEditServiceModalViewModel类,增加UI显示需要的实体数据形式。
        public class CreateOrEditServiceModalViewModel
        {
            public CreateOrEditServiceDto Service { get; set; }
    
            public bool IsEditMode => Service.Id.HasValue;
    
            public List<ComboboxItemDto> TaxItems { get; set; }
        }
  7. 修改ServiceController,增加UI层数据模型数据加载。
           public async Task<PartialViewResult> CreateOrEditModal(Guid? id)
            {
                GetServiceForEditOutput getServiceForEditOutput;
    
                if (id.HasValue)
                {
                    getServiceForEditOutput = await _servicesAppService.GetServiceForEdit(new EntityDto<Guid> { Id = (Guid)id });
                }
                else
                {
                    getServiceForEditOutput = new GetServiceForEditOutput
                    {
                        Service = new CreateOrEditServiceDto(),
                        TaxeItems = await _servicesAppService.GetAllTaxes()
                    };
                    getServiceForEditOutput.Service.EffectiveDate = DateTime.Now;
                    getServiceForEditOutput.Service.EndDate = DateTime.Now;
                }
    
                var viewModel = new CreateOrEditServiceModalViewModel()
                {
                    Service = getServiceForEditOutput.Service,
                    TaxItems = getServiceForEditOutput.TaxeItems
                };
    
                return PartialView("_CreateOrEditModal", viewModel);
            }
  8. 修改_CreateOrEditModal.cshtml文件增加Taxes数据控件。
                <div class="form-group">
                    <label for="Service_Taxes">@L("Taxes")</label>
                    <select id="Service_Taxes" class="form-control select2" style="width:100%;" multiple>
                        @foreach (var item in Model.TaxItems)
                        {
                        <option value="@item.Value" selected="@item.IsSelected">@item.DisplayText</option>
                        }
                    </select>
                </div>
  9. 修改_CreateOrEditModal.js文件,增加“select2”组件的初始中化。
                modal.find("#Service_Taxes")
                    .select2({
                        placeholder: "Select a tax",
                        tags: true
                    });

     增加获取选择数据结果的代码。

           this.save = function() {
                if (!_$serviceInformationForm.valid()) {
                    return;
                }
    
                // taxes select - post
                var $selectElement = $('#Service_Taxes');
    
                var inputTaxes = [];
    
                $.each($selectElement.select2('data'), function (index, item) {
                    inputTaxes.push({
                        name: item.text,
                        value: item.id
                    });
                });
    
                var service = _$serviceInformationForm.serializeFormToObject();
    
                service.taxItems = inputTaxes;
    
                _modalManager.setBusy(true);
    
                _servicesService.createOrEdit(
                    service
                ).done(function() {
                    abp.notify.info(app.localize('SavedSuccessfully'));
                    _modalManager.close();
                    abp.event.trigger('app.createOrEditServiceModalSaved');
                }).always(function() {
                    _modalManager.setBusy(false);
                });
            };

     

到这里ABP Zero框架中添加“Many-To-Many”关系的实体关系的方法已经全部分修改完毕。

 

posted @ 2021-11-30 15:19  安逸竹  阅读(79)  评论(0编辑  收藏  举报