对于父表中的每一行,子表中都有许多子行。但是子行对于具有“JointId”和“NdtId”的每个父行都是唯一的,当我从存储库调用“GetLineJointsForNdtSelectionAsync”时,我希望使用“JointId”和“NdtId”过滤数据。 “JointId”可在解析器中访问,“NdtId”必须从存储库中的“GetLineJointsForNdtSelectionAsync”传递:
.ProjectTo<Models.Output.Piping.LineJoints.LineJointForNdtSelection>(
_mapper.ConfigurationProvider,
new { ndtId = query.NdtId })
但是从“GetLineJointsForNdtSelectionAsync”传递到解析器类的值是空 GUID。然后我使用“(Guid)context.Items[“ndtId”]”来获取配置文件类中传递的值,但出现以下异常:
无法从创建地图表达式。 (Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint) 到 String.NdtType (System.String) 映射类型:LineJoint -> LineJointForNdtSelection Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint -> Ces.Caspian。 Models.Output.Piping.LineJoints.LineJointForNdtSelection 类型映射配置:LineJoint -> LineJointForNdtSelection Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint -> Ces.Caspian.Models.Output.Piping.LineJoints.LineJointForNdtSelection 目标成员:NdtType。
父表:
public class LineJoint : EntityBase
{
public const int JointNoIndexMaxLength = 5;
public const int JointNoMaxLength = 20;
public LineJoint()
{
}
public LineJoint(Guid? userId) : base(userId)
{
}
public Guid? ContractorId { get; set; }
public Guid? LineSheetId { get; set; }
public string? JointNo { get; set; }
public Guid? ScheduleId { get; set; }
public Guid? ConnectionTypeId { get; set; }
public Guid? EndStatusId { get; set; }
public Guid? EndTypeId { get; set; }
public Guid? JointTypeId { get; set; }
public Guid? LocationId { get; set; }
public Guid? WeldTypeId { get; set; }
public int Revision { get; set; }
public Guid? TestPackageId { get; set; }
// Navigation
public Domain.Entities.Project.Contractors.Contractor? Contractor { get; set; }
public Domain.Entities.Piping.LineSheets.LineSheet? LineSheet { get; set; }
public Domain.Entities.Piping.ConnectionTypes.ConnectionType? ConnectionType { get; set; }
public Domain.Entities.Piping.EndTypes.EndType? EndType { get; set; }
public Domain.Entities.Piping.EndStatuses.EndStatus? EndStatus { get; set; }
public Domain.Entities.Piping.JointTypes.JointType? JointType { get; set; }
public Domain.Entities.Piping.Locations.Location? Location { get; set; }
public Domain.Entities.Piping.WeldTypes.WeldType? WeldType { get; set; }
public Domain.Entities.TestPackage.TestPackages.TestPackage? TestPackage { get; set; }
public Domain.Entities.Piping.Schedules.Schedule? Schedule { get; set; }
public List<Domain.Entities.Piping.NdtStatuses.NdtStatus>? NdtStatuses { get; set; }
}
儿童桌:
public class NdtStatus : Entities.EntityBase
{
public const int NDTNoMaxLength = 50;
public NdtStatus()
{
}
public NdtStatus(Guid? userId) : base(userId)
{
}
public Guid? LineJointId { get; set; }
public Guid? NdtId { get; set; }
public bool Required { get; set; }
public bool Exempted { get; set; }
public string? NdtNo { get; set; }
public Guid? NdtTypeId { get; set; }
// Navigation
public Domain.Entities.Piping.LineJoints.LineJoint? LineJoint { get; set; }
public Domain.Entities.Piping.Ndts.Ndt? Ndt { get; set; }
public Domain.Entities.Piping.NdtTypes.NdtType? NdtType { get; set; }
}
输出型号:
public class LineJointForNdtSelection : OutputModelEssentials
{
// From parent table
public Guid JointId { get; set; }
public string? Contractor { get; set; }
public string? SheetNo { get; set; }
public string? JointNo { get; set; }
public string? ConnectionType { get; set; }
public string? EndStatus { get; set; }
public string? EndType { get; set; }
public string? JointType { get; set; }
public string? Location { get; set; }
public string? PackageNo { get; set; }
// From child table
public string? Ndt { get; set; }
public string? NdtType { get; set; }
public bool Required { get; set; }
public bool Exempted { get; set; }
public string? NdtNo { get; set; }
public string? RequestNo { get; set; }
public string? ReportNo { get; set; }
public string? Result { get; set; }
}
用于映射的 AutoMapper 配置文件类:
public class LineJointForNdtSelection : AutoMapper.Profile
{
public LineJointForNdtSelection()
{
CreateMap<
Domain.Entities.Piping.LineJoints.LineJoint,
Models.Output.Piping.LineJoints.LineJointForNdtSelection>()
// From parent table
.ForMember(x => x.JointId, x => x.MapFrom(x => x.Id))
.ForMember(x => x.Contractor, x => x.MapFrom(x => x.Contractor.Name))
.ForMember(x => x.SheetNo, x => x.MapFrom(x => x.LineSheet.SheetNo))
.ForMember(x => x.ConnectionType, x => x.MapFrom(x => x.ConnectionType.Name))
.ForMember(x => x.EndStatus, x => x.MapFrom(x => x.EndStatus.Name))
.ForMember(x => x.EndType, x => x.MapFrom(x => x.EndType.Name))
.ForMember(x => x.JointType, x => x.MapFrom(x => x.JointType.Name))
.ForMember(x => x.Location, x => x.MapFrom(x => x.Location.Name))
.ForMember(x => x.PackageNo, x => x.MapFrom(x => x.TestPackage.TestPackageNo))
// From child table
.ForMember(x => x.NdtType, opt => opt.MapFrom((src, dest, destMember, context)
=> new Profiles.Piping.NdtStatuses.Resolvers.NdtTypeResolver((Guid)context.Items["ndtId"])
.Resolve(src, dest, destMember, context)));
;
}
}
客户解析器:
public class NdtTypeResolver : IValueResolver<
Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint,
Ces.Caspian.Models.Output.Piping.LineJoints.LineJointForNdtSelection,
string?>
{
private Guid? _ndtId;
public NdtTypeResolver()
{
}
public NdtTypeResolver(Guid? ndtId = null)
{
_ndtId = ndtId;
}
public string? Resolve(
Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint source,
Ces.Caspian.Models.Output.Piping.LineJoints.LineJointForNdtSelection destination,
string? destMember,
ResolutionContext context)
{
return source.NdtStatuses?.FirstOrDefault(c
=> c.LineJointId == source.Id && c.NdtId == _ndtId)?.NdtType?.Name ?? string.Empty;
}
}
存储库方法:
public async Task<List<Models.Output.Piping.LineJoints.LineJointForNdtSelection>> GetLineJointsForNdtSelectionAsync(
Models.Input.Queries.Piping.LineJoints.GetLineJointsForNdtSelection query)
{
var result = await _dbContext.LineJoints
.Where(x => x.LineSheet.LineNumberId == query.LineNumberId)
.ProjectTo<Models.Output.Piping.LineJoints.LineJointForNdtSelection>(
_mapper.ConfigurationProvider,
new { ndtId = query.NdtId })
.AsNoTracking()
.ToListAsync()
;
return result;
}
我已将解析器注册到服务,但没有解决问题。有一个简单的解决方案,但我认为这不是最好的解决方案,但有效。在我的上一个解决方案中,我必须为每个“NdtId”创建多配置文件类,然后在我的存储库中检查哪个“Id”传递给方法,然后调用内部方法来获取所需的数据,然后返回给用户。
我的问题已经解决了。当我使用 ProjectTo 将数据从数据库映射到类时,_mapper.ConfigurationProvider 之后的第二个参数无法为 ResolutionContext 赋值。最终的解决方案是,首先从数据库映射数据,然后,为了将数据映射到输出模型,我们可以为ResolutionContext赋值,以将值传递给解析器。事实上,我只是重构了我的存储库方法:
public async Task<List<Models.Output.Piping.LineJoints.LineJointForNdtSelection>> GetLineJointsForNdtSelectionAsync(
Models.Input.Queries.Piping.LineJoints.GetLineJointsForNdtSelection query)
{
var initialResult = await _dbContext.LineJoints
.Where(x => x.LineSheet.LineNumberId == query.LineNumberId)
.Select(s => new Models.Output.Piping.LineJoints.LineJointForNdtSelection
{
JointId = s.Id,
Contractor = s.Contractor == null ? null : s.Contractor.Name,
SheetNo = s.LineSheet == null ? null : s.LineSheet.SheetNo.ToString(),
JointNo = s.JointNo == null ? null : s.JointNo,
ConnectionType = s.ConnectionType == null ? null : s.ConnectionType.Name,
EndStatus = s.EndStatus == null ? null : s.EndStatus.Name,
EndType = s.EndType == null ? null : s.EndType.Name,
JointType = s.JointType == null ? null : s.JointType.Name,
Location = s.Location == null ? null : s.Location.Name,
PackageNo = s.TestPackage == null ? null : s.TestPackage.TestPackageNo,
// NDT Status
Ndt = s.NdtStatuses == null ? null :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? null :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).Ndt.Name,
NdtType = s.NdtStatuses == null ? null :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? null :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).NdtType.Name,
Required = s.NdtStatuses == null ? false :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? false :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).Required,
Exempted = s.NdtStatuses == null ? false :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? false :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).Exempted,
NdtNo = s.NdtStatuses == null ? null :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? null :
s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).NdtNo,
RequestNo = string.Empty,
ReportNo = string.Empty,
Result = string.Empty,
})
.AsNoTracking()
.ToListAsync()
;
var data = _mapper.Map<List<Models.Output.Piping.LineJoints.LineJointForNdtSelection>>(initialResult, option =>
{
option.Items["ndtId"] = query.NdtId;
});
return data;
}
通过自定义解析器映射所需的属性(现在我可以使用 context.Items["ndtId"]):
.ForMember(x => x.Required, opt => opt.MapFrom((src, dest, destMember, context)
=> new Profiles.Piping.NdtStatuses.Resolvers.ExemptedResolver((Guid?)context.Items["ndtId"])
.Resolve(src, dest, destMember, context)))