如何简化Dynamic Linq中的Join层级,直接引用关联表别名
问题描述
使用Dynamic LINQ时,每次添加Join操作都会生成新的嵌套层级,编写动态Where子句时格外繁琐。当前访问关联表字段必须写冗长的t.t.t...嵌套路径,希望能给每个Join指定别名,直接通过别名访问对应的关联表。
当前的查询代码如下:
context.Trips .GroupJoin(context.Entities, trips => trips.BeneficiaryEntitiesId, beneficiarys => beneficiarys.Id, (trips, tripsEntities) => new { trips, tripsEntities }) .SelectMany(t => t.tripsEntities.DefaultIfEmpty(), (t, beneficiarys) => new { t, beneficiarys }) .GroupJoin(context.Items, t => t.t.trips.ItemId, items => items.Id, (t, tripsItems) => new { t, tripsItems }) .SelectMany(t => t.tripsItems.DefaultIfEmpty(), (t, items) => new { t, items }) .Join(context.Entities, t => t.t.t.t.trips.CarrierEntitiesId, carriers => carriers.Id, (t, carriers) => new { t, carriers }) .Join(context.Vehicl, t => t.t.t.t.t.trips.VehiclId, vehicls => vehicls.Id, (t, vehicls) => new { t, vehicls }) .Join(context.DefineLists, t => t.vehicls.VehiclType, vehiclsType => vehiclsType.Id, (t, vehiclsType) => new { t, vehiclsType }) .Join(context.Drivers, t => t.t.t.t.t.t.t.trips.EntryDriverId, endrivers => endrivers.Id, (t, endrivers) => new { t, endrivers }) .GroupJoin(context.Drivers, t => t.t.t.t.t.t.t.t.trips.OutputDriverId, oudrivers => oudrivers.Id, (t, oudrivers) => new { t, oudrivers }) .SelectMany(t => t.oudrivers.DefaultIfEmpty(), (t, oudrivers) => new { t, oudrivers }) .Where(@$"(t.t.t.vehiclsType.ListType==1 {SDateWhere}{EDateWhere}) {SubWhere}{MainWhere}", StartDate, ed) .Select(s => new { s.t.t.t.t.t.t.t.t.t.trips.Id, TripsFullNo = $"{s.t.t.t.t.t.t.t.t.t.trips.TripsFullNo} {s.t.t.t.t.t.t.t.t.t.trips.TripsNo}", OperationTtype = s.t.t.t.t.t.t.t.t.t.trips.Loading ? operationTtypes[s.t.t.t.t.t.t.t.t.t.trips.OperationTtype ?? 0] : $"{Language.ListOperateTransfer} {Language.ListEmpt}", Vehicl = $"{s.t.t.t.t.vehicls.LicensePlate}/{s.t.t.t.vehiclsType.ListItem}", CarrierEntities = s.t.t.t.t.t.carriers.EntitieName, BeneficiaryEntities = s.t.t.t.t.t.t.t.t.beneficiarys!.EntitieName, Item = s.t.t.t.t.t.t.items!.NoName, Driver = $"{s.t.t.endrivers.DriverLicense}/{s.t.t.endrivers.DriverName}" }).OrderByDescending(o=>o.Id)
解决方案
核心思路是避免嵌套匿名类型,每次关联后构造扁平的匿名对象,把需要保留的所有实体(主表+已关联表)直接作为属性暴露,并给每个关联表指定明确的别名。这样后续操作就能直接通过别名访问,无需嵌套路径。
修改后的代码示例:
context.Trips // 左连接受益方实体 .GroupJoin(context.Entities, trips => trips.BeneficiaryEntitiesId, beneficiarys => beneficiarys.Id, (trips, tripsEntities) => new { trips, tripsEntities }) .SelectMany(t => t.tripsEntities.DefaultIfEmpty(), (t, beneficiary) => new { t.trips, Beneficiary = beneficiary }) // 左连接物品信息 .GroupJoin(context.Items, joined => joined.trips.ItemId, items => items.Id, (joined, tripsItems) => new { joined.trips, joined.Beneficiary, tripsItems }) .SelectMany(t => t.tripsItems.DefaultIfEmpty(), (t, item) => new { t.trips, t.Beneficiary, Item = item }) // 内连接承运方实体 .Join(context.Entities, joined => joined.trips.CarrierEntitiesId, carriers => carriers.Id, (joined, carrier) => new { joined.trips, joined.Beneficiary, joined.Item, Carrier = carrier }) // 内连接车辆信息 .Join(context.Vehicl, joined => joined.trips.VehiclId, vehicls => vehicls.Id, (joined, vehicl) => new { joined.trips, joined.Beneficiary, joined.Item, joined.Carrier, Vehicl = vehicl }) // 内连接车辆类型字典 .Join(context.DefineLists, joined => joined.Vehicl.VehiclType, vehiclTypes => vehiclTypes.Id, (joined, vehiclType) => new { joined.trips, joined.Beneficiary, joined.Item, joined.Carrier, joined.Vehicl, VehiclType = vehiclType }) // 内连接入场司机 .Join(context.Drivers, joined => joined.trips.EntryDriverId, endrivers => endrivers.Id, (joined, entryDriver) => new { joined.trips, joined.Beneficiary, joined.Item, joined.Carrier, joined.Vehicl, joined.VehiclType, EntryDriver = entryDriver }) // 左连接出场司机 .GroupJoin(context.Drivers, joined => joined.trips.OutputDriverId, oudrivers => oudrivers.Id, (joined, outputDrivers) => new { joined.trips, joined.Beneficiary, joined.Item, joined.Carrier, joined.Vehicl, joined.VehiclType, joined.EntryDriver, outputDrivers }) .SelectMany(t => t.outputDrivers.DefaultIfEmpty(), (t, outputDriver) => new { t.trips, t.Beneficiary, t.Item, t.Carrier, t.Vehicl, t.VehiclType, t.EntryDriver, OutputDriver = outputDriver }) // 直接用别名访问字段,无需嵌套 .Where(@$"(VehiclType.ListType==1 {SDateWhere}{EDateWhere}) {SubWhere}{MainWhere}", StartDate, ed) .Select(s => new { s.trips.Id, TripsFullNo = $"{s.trips.TripsFullNo} {s.trips.TripsNo}", OperationTtype = s.trips.Loading ? operationTtypes[s.trips.OperationTtype ?? 0] : $"{Language.ListOperateTransfer} {Language.ListEmpt}", Vehicl = $"{s.Vehicl.LicensePlate}/{s.VehiclType.ListItem}", CarrierEntities = s.Carrier.EntitieName, BeneficiaryEntities = s.Beneficiary!.EntitieName, Item = s.Item!.NoName, Driver = $"{s.EntryDriver.DriverLicense}/{s.EntryDriver.DriverName}" }) .OrderByDescending(o => o.Id)
关键说明:
- 每次完成
Join/GroupJoin+SelectMany后,都构造一个扁平的匿名类型,将当前所有需要的实体(主表trips+已关联的Beneficiary、Item等)直接作为属性,同时给每个关联表指定清晰的别名。 - 后续的关联操作、Where条件、Select投影都可以直接通过别名访问对应表的字段,彻底摆脱冗长的
t.t.t...嵌套路径。 - 这种写法不仅让Dynamic LINQ的Where子句更简洁,也大幅提升了整体代码的可读性和可维护性。
内容的提问来源于stack exchange,提问作者خالد بشير
相关产品推荐
相关产品推荐

