首页 > 其他分享 >abp-vnext-pro 实战(八,聚合根的写法,客户M:N地址)

abp-vnext-pro 实战(八,聚合根的写法,客户M:N地址)

时间:2023-08-19 23:35:35浏览次数:37  
标签:vnext set string get pro private Id abp public

参考数据字典模块的写法

/// <summary>
/// 地址
/// </summary>
public class Address : FullAuditedAggregateRoot<Guid>,IMultiTenant
{

    public Guid? TenantId { get; protected set; }

    /// <summary>
    /// 公司名
    /// </summary>
    public string Company { get; private set; }
    /// <summary>
    /// 城市
    /// </summary>
    public string City { get; private set; }
    /// <summary>
    /// 地址
    /// </summary>
    public string Address1 { get; private set; }
    /// <summary>
    /// 邮编
    /// </summary>
    public string ZipPostalCode { get; private set; }
    /// <summary>
    /// 电话
    /// </summary>
    public string PhoneNumber { get; private set; }

    public List<Customer> Customers { get; private set; }  


}

public class Customer : FullAuditedAggregateRoot<Guid>, IMultiTenant
{

    public Guid? TenantId { get; protected set; }
    /// <summary>
    /// 客户名字
    /// </summary>
    public string Name { get; private set; }
    /// <summary>
    /// 客户编号
    /// </summary>
    public string Code { get; private set; }
    /// <summary>
    /// 客户简称
    /// </summary>
    public string ShortName { get; private set; }
    /// <summary>
    /// 组织代码
    /// </summary>
    public string OrgCode { get; private set; }


    public List<Address> CustAddresses { get; private set; }
}

application.contract 项目里的PageAddressInput,增加一个客户字段custId用于查询关联, nswag/refresh.bat 要执行刷新。

public class PageAddressInput: PagingBase
{
    public Guid CustId { get; set; }
}

 对应的CreateAddressInput 也要加一个CustId的字段,而更新地址时不需要改变CustId

 

EntityFrameworkCore 项目里 ERPDbContextModelCreatingExtensions 多对多的默认写法

                b.HasMany(b => b.CustAddresses).WithMany(c=>c.Customers)
                .UsingEntity("CustAddresses");

对应生成的数据库结构是这样

            migrationBuilder.CreateTable(
                name: "CustAddresses",
                columns: table => new
                {
                    CustAddressesId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
                    CustomersId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_CustAddresses", x => new { x.CustAddressesId, x.CustomersId });
                    table.ForeignKey(
                        name: "FK_CustAddresses_CrmAddresses_CustAddressesId",
                        column: x => x.CustAddressesId,
                        principalTable: "CrmAddresses",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_CustAddresses_CrmCustomer_CustomersId",
                        column: x => x.CustomersId,
                        principalTable: "CrmCustomer",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                })
                .Annotation("MySql:CharSet", "utf8mb4");

            migrationBuilder.CreateIndex(
                name: "IX_CustAddresses_CustomersId",
                table: "CustAddresses",
                column: "CustomersId");

 假如要指定中间表的字段名,则2个对象都要指定

 builder.Entity<Customer>(b =>
            {
                b.ToTable(ERPConsts.CRMDbTablePrefix + "Customer", ERPConsts.DbSchema);
                b.ConfigureByConvention(); 
                b.HasMany(b => b.CustAddresses).WithMany(c=>c.Customers)
                .UsingEntity("CustAddresses",
                l => l.HasOne(typeof(Customer)).WithMany().HasForeignKey("Customer_Id").HasPrincipalKey(nameof(Customer.Id)),
                r => r.HasOne(typeof(Address)).WithMany().HasForeignKey("Address_Id").HasPrincipalKey(nameof(Address.Id)),
                j => j.HasKey("Customer_Id", "Address_Id"));

                //The skip navigation 'Address.Customers' doesn't have a foreign key associated with it.
                //Every skip navigation must have a configured foreign key.
            });

            builder.Entity<Address>(b =>
            {
                //b.ToTable(ERPConsts.CRMDbTablePrefix + nameof(Address).Pluralize
                b.ToTable(ERPConsts.CRMDbTablePrefix + "Addresses");

                b.ConfigureByConvention();
                b.HasMany(b => b.Customers).WithMany(c => c.CustAddresses)
                .UsingEntity("CustAddresses",
                l => l.HasOne(typeof(Customer)).WithMany().HasForeignKey("Customer_Id").HasPrincipalKey(nameof(Customer.Id)),
                r => r.HasOne(typeof(Address)).WithMany().HasForeignKey("Address_Id").HasPrincipalKey(nameof(Address.Id)),
                j => j.HasKey("Customer_Id", "Address_Id"));
            });

 

=======================================多对多前端页面=============================

客户列表界面A,点击地址按钮,新开一个tab页面B,显示该客户下面的地址列表。

A页面path= setting 的某个链接或按钮,按下新开tab 页面

1. 先在router/module里定义一个隐藏菜单,path是 preViewCode

 {
      path: 'preViewCode',
      name: 'PreViewCode',
      component: () => import('/@/views/generators/PreViewCode.vue'),
      meta: {
        title: '预览',
        icon: 'ant-design:file-sync-outlined',
        hideMenu: true,
      },

2. A页面index.vue里面 click事件里用router.push传path和参数

<a-button class="!ml-4" type="primary" @click="addTabPage">预览</a-button>  

A页面要引入 useRouter 

import { useRouter } from 'vue-router';

setup() {
const router = useRouter();

}

      //跳转到地址列表页,并传递客户ID
      async function addTabPage(record: Recordable) {
        try {
          await router.push({
            name: 'AddressPage',
            query: { custId: record.id },
          });
        } catch (error) { }
      }

3. 再在B页面的index.vue 页面, 引入useRoute ,而不是useRouter, 差一个字母,很容易看错

  import { useRoute } from 'vue-router';
  setup() {
      const route = useRoute();
      const queryParams = route.query;
      console.log(queryParams.custId);

      // table配置
      const [registerTable, { reload }] = useTable({
        columns: tableColumns,
        formConfig: {
          labelWidth: 70,
          schemas: searchFormSchema,
        },
        api: pageAsync11,  //



       function pageAsync11(a : any) {
         console.log("queryParams.custId传到params: PageAddressInput");
        //params: any
        a.custId=queryParams.custId;
        return pageAsync(a);
      }

Domain 项目的 AddressManager

   private readonly IAddressRepository _addressRepository;
    private readonly ICustomerRepository _customerRepository;
    private readonly IObjectMapper _objectMapper;

    public AddressManager(IAddressRepository addressRepository, IObjectMapper objectMapper, ICustomerRepository customerRepository)
    {
        _addressRepository = addressRepository;
        _objectMapper = objectMapper;
        _customerRepository = customerRepository;
    }
    public async Task<List<AddressDto>> GetListAsync(Guid custId,int maxResultCount = 10, int skipCount = 0)
    {
        var list = await _customerRepository.GetCustAddressListAsync(custId, maxResultCount, skipCount);
        //var list = await _addressRepository.GetListAsync(maxResultCount, skipCount);
        return _objectMapper.Map<List<Address>, List<AddressDto>>(list);
    }

    /// <summary>
    /// 创建地址
    /// </summary>
    public async Task<AddressDto> CreateAsync(
        Guid id,
        int countryId,
        int stateProvinceId,
        string firstName,
        string lastName,
        string email,
        string company,
        string city,
        string address1,
        string zipPostalCode,
        string phoneNumber,
        Guid custId
    )
    {
        var entity = new Address(id, countryId, stateProvinceId, firstName, lastName, email, company, city, address1, zipPostalCode, phoneNumber);
        entity = await _addressRepository.InsertAsync(entity);
        //客户地址增加关联
        var cust = await _customerRepository.GetAsync(custId);
        cust.AddAddress(entity);
        return _objectMapper.Map<Address, AddressDto>(entity);
    }

 

标签:vnext,set,string,get,pro,private,Id,abp,public
From: https://www.cnblogs.com/zitjubiz/p/17622906.html

相关文章

  • Gym103687D The Profiteer:回滚莫队信息双指针可以做到线性对数
    标题写得好所谓的回滚莫队信息意思是,设信息保存在两个大小分别为\(a,b\)的结构上,将这两个信息进行合并得到大小为\(a+b\)的信息需要的时间为\(\Omega(\min\{a,b\}\cdotf(n))\);而给定一个大小为\(1\)的信息,可以在\(\mathrmO(f(n))\)时间内将它加入到任何一个结构中......
  • [Mac软件]MacCleaner 3 PRO 3.2.1应用程序清理和卸载
    应用介绍MacCleanerPRO是一个应用程序包,将帮助您清除磁盘空间并加快Mac的速度!MacCleanerPRO-让您的Mac始终快速、干净和有条理。AppCleaner&UninstallerPRO-完全删除未使用的应用程序并管理Mac扩展。磁盘空间分析仪PRO-分析磁盘空间的使用情况,并找到最庞大的内容。重复文......
  • MacbookPro 17年款老机器升级Macos10.15.7挺好的
    MacbookPro17年款老机器升级Macos10.15.7挺好的由于需要安装一些软件,至少需要10.14或者10.15,所以,把MacBookPro17年款的老机器进行了升级,原装的系统是10.12.6.安装之前在网上搜索了各种升级的利弊,有升级成功的,也有很多说升级之后不能使用,然后又降级的。搞得犹豫了好一会,最后还......
  • [转]By not providing "FindEigen3.cmake" in CMAKE_MODULE_PATH this project has
    在编译安装的时候出现如下问题,是Eigen3的Cmake依赖问题,已经安装eigen3,但在项目的find_package(Eigen3QUERIED)中,无法找到FindEigen3.Cmake. CMakeErroratloam_velodyne/CMakeLists.txt:13(find_package):Bynotproviding"FindEigen3.cmake"inCMAKE_MODULE_......
  • PostgreSQL 源码性能诊断(perf profiling)指南(含火焰图生成分析FlameGraph) - 珍藏级
    PostgreSQL源码性能诊断(perfprofiling)指南(含火焰图生成分析FlameGraph)-珍藏级作者digoal日期2016-11-28标签PostgreSQL,Linux,perf,性能诊断,stap,systemtap,strace,dtrace,dwarf,profiler,perf_events,probe,dynamicprobe,tracepoint......
  • vue数据传递【父子组件】-父子props,子父$emit
    一、父子组件传递1、父组件数据传递给子组件【props】父组件的数据变化时,子组件会自动更新在父组件中引用子组件<子组件name/>import子组件from./子组件位置/子组件所在vue.vue在组件中注册子组件components:{子组件名称}子组件可以通过props选项声明接收该prop......
  • SyntaxError: /xxxx.vue: Unexpected token, expected “,“,[object Promise]export {
    本地老工程vue2.7.x+webpack4在升级webpack5的时候遇启动和打包报错:SyntaxError:SyntaxError:/xxxxx.vueUnexpectedtoken,expected","(1:8)>1|[objectPromise]|^2|export{render,staticRenderFns}最后才发现是prettier导致的。推荐看......
  • Math Problem
                                                  E-MathProblem##题面翻译**【题目描述】**给定两个正整数$n$和$k$,您可以进行以下两种操作任意次(包括零次):-选择一个整数......
  • \\NSHA10320UAP.ubsglobal-prod.msad.ubs.net\d$\data\部署包\组件全量0818\组
    com.yss.ams.bbzx-202308031009-V2.0.0.10.39-20221115.jarcom.yss.ams.reportConfigSetting-20230714135143.jarcom.yss.ams.ReportViewer-202308031009-V2.0.0.10.39-20221115.jarcom.yss.ams.website-202308031009-V2.0.0.10.39-20221115.jarcom.yss.sofa.foundation.autho......
  • OpenCV CAP_PROP_FRAME_COUNT 获取视频帧数问题
    OpenCV读取视频,可以通过属性CAP_PROP_FRAME_COUNT获取视频的总帧数,但是有些视频通过该属性获取的帧数和实际遍历整个视频的帧数不一样。importcv2ascvvideo='video.mp4'cap=cv.VideoCapture(video)frames=cap.get(cv.CAP_PROP_FRAME_COUNT)#通过属性获取帧数......