参考数据字典模块的写法
/// <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