Я пытаюсь создать Dto, которое будет отображать множество вложенных данных на основе введенных пользователем параметров из интерфейса веб-приложения.
public async Task<IActionResult> GetData(int? version,
int[] subSpecialty,
int[] pathway,
int[] job,
int[] opActivity,
int[] pointOfDelivery,
int[] theatreList)
Пользовательский ввод позволяет вводить несколько отдельных параметров для отображения нескольких записей таблицы, поэтому параметры принимаются как массивы.
У меня было несколько попыток сопоставить эти данные безуспешно, моя текущая попытка кажется, что она должна работать и выглядит так:
var dto = await
_dbContext.ModelVersion
.Where(mv => version == mv.Id)
.Select(mv => new DataGetDto
{
ModelId = mv.Id,
SubSpecialtyDto = mv.SubSpecialties
.Where(ss => ss.ModelId == version && subSpecialty.Contains(ss.SubSpecialtyTypeId))
.Select(ss => new SubSpecialtyDto
{
CostOp = ss.CostOp,
CostTh = ss.CostTh,
ModelId = ss.ModelId,
SubSpecialtyTypeId = ss.SubSpecialtyTypeId,
FacilityActivityDto = mv.FacilityActivities
.Where(fa => fa.ModelId == version && pointOfDelivery.Contains(fa.PointOfDeliveryId) && pathway.Contains(fa.PathwayId) && subSpecialty.Contains(fa.SubSpecialtyTypeId))
.Select(fa => new FacilityActivityDto
{
PatientCases = fa.PatientCases,
AverageIncome = fa.AverageIncome,
CostToBookSinglePatient = fa.CostToBookSinglePatient,
AverageCaseTime = fa.AverageCaseTime,
PoDproportion = fa.PoDproportion,
LengthOfStay = fa.LengthOfStay,
PatientHandlingCost = fa.PatientHandlingCost,
CostPerDay = fa.CostPerDay,
BedOccupancy = fa.BedOccupancy,
InplantCost = fa.InplantCost,
OverHead = fa.OverHead,
ModelId = fa.ModelId,
PointOfDeliveryId = fa.PointOfDeliveryId,
PathwayId = fa.PathwayId,
SubSpecialtyTypeId = fa.SubSpecialtyTypeId
}),
OutPatientActivityDto = mv.OutPatientActivities
.Where(opa => opa.ModelId == version && opActivity.Contains(opa.ActivityId) && pathway.Contains(opa.PathwayId) && subSpecialty.Contains(opa.SubSpecialtyTypeId))
.Select(opa => new OutPatientActivityDto
{
PatientsSeenOp = opa.PatientsSeenOp,
AverageIncomeOp = opa.AverageIncomeOp,
ConversionRate = opa.ConversionRate,
ModelId = opa.ModelId,
ActivityId = opa.ActivityId,
PathwayId = opa.PathwayId,
SubSpecialtyTypeId = opa.SubSpecialtyTypeId
}),
OutPatientOperationalFactorDto = mv.OutPatientOperationalFactors
.Where(opof => opof.ModelId == version && opActivity.Contains(opof.ActivityId) && subSpecialty.Contains(opof.SubSpecialtyTypeId))
.Select(opof => new OutPatientOperationalFactorDto
{
BookingRateOp = opof.BookingRateOp,
DnarateOp = opof.DnarateOp,
PatientCancellationRateOp = opof.PatientCancellationRateOp,
HospitalCancellationRateOp = opof.HospitalCancellationRateOp,
PatientLateNoticeRateOp = opof.PatientLateNoticeRateOp,
HospitalLateNoticeRateOp = opof.HospitalLateNoticeRateOp,
CostToBookSingleOutPatient = opof.CostToBookSingleOutPatient,
ModelId = opof.ModelId,
ActivityId = opof.ActivityId,
SubSpecialtyTypeId = opof.SubSpecialtyTypeId
}),
SkillMixDistributionDto = mv.SkillMixDistributions
.Where(smd => smd.ModelId == version && opActivity.Contains(smd.JobTypeId) && pathway.Contains(smd.PathwayId) && subSpecialty.Contains(smd.SubSpecialtyTypeId))
.Select(smd => new SkillMixDistributionDto
{
WorkingWeeksPerYearOp = smd.WorkingWeeksPerYearOp,
WorkingWeeksPerYearTh = smd.WorkingWeeksPerYearTh,
CostPerPa = smd.CostPerPa,
DistributionOp = smd.DistributionOp,
DistributionTh = smd.DistributionTh,
AdminTimeOp = smd.AdminTimeOp,
SetupTimeOp = smd.SetupTimeOp,
CacheUpTimeOp = smd.CacheUpTimeOp,
PatientFacingTimeOp = smd.PatientFacingTimeOp,
ModelId = smd.ModelId,
JobTypeId = smd.JobTypeId,
PathwayId = smd.PathwayId,
SubSpecialtyTypeId = smd.SubSpecialtyTypeId,
}),
TheatreListStructureDto = mv.TheatreListStructures
.Where(tls => tls.ModelId == version && opActivity.Contains(tls.TheatreListTypeId) && pathway.Contains(tls.SubSpecialtyTypeId))
.Select(tls => new TheatreListStructureDto
{
PreOpWardRound = tls.PreOpWardRound,
PostOpWardRound = tls.PostOpWardRound,
FacingPatientTime = tls.FacingPatientTime,
BreakTime = tls.BreakTime,
PreferredSessionType = tls.PreferredSessionType,
ModelId = tls.ModelId,
TheatreListTypeId = tls.TheatreListTypeId,
SubSpecialtyTypeId = tls.SubSpecialtyTypeId
}),
TheatreOperationalFactorDto = mv.TheatreOperationalFactors
.Where(tof => tof.ModelId == version && opActivity.Contains(tof.PointOfDeliveryId) && subSpecialty.Contains(tof.SubSpecialtyTypeId))
.Select(tof => new TheatreOperationalFactorDto
{
CostToRunListTh = tof.CostToRunListTh,
PreOpAnaesthetic = tof.PreOpAnaesthetic,
PostOpAnaesthetic = tof.PostOpAnaesthetic,
KnifeToSkin = tof.KnifeToSkin,
Gaps = tof.Gaps,
LateStart = tof.LateStart,
EarlyFinish = tof.EarlyFinish,
InSessionUtilisation = tof.InSessionUtilisation,
ModelId = tof.ModelId,
PointOfDeliveryId = tof.PointOfDeliveryId,
SubSpecialtyTypeId = tof.SubSpecialtyTypeId
})
})
})
.ToListAsync();
Когда я пытаюсь проверить этот код, я пишу это в URL.
Data?version=1&subSpecialty=1&pathway=1&job=1&opActivity=1&pointOfDelivery=1&theatreList=1
Это удачно отображает идентификатор версии (ModelId), как и ожидалось, но возвращает ошибку типа System.InvalidOperationException при входе на первый уровень вложенности:
переменное изображение часов
- Current '((System.Linq.AsyncEnumerable.AsyncIterator<Medicor.Portal.Models.DacPlannerDtos.SubSpecialtyDto>)((Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.EnumerableAdapter<Medicor.Portal.Models.DacPlannerDtos.SubSpecialtyDto>)(new System.Collections.Generic.ICollectionDebugView<Medicor.Portal.Models.DacPlannerDtos.DataGetDto>(dto).Items[0]).SubSpecialtyDto).Results).Current' threw an exception of type 'System.InvalidOperationException' Medicor.Portal.Models.DacPlannerDtos.SubSpecialtyDto {System.InvalidOperationException}
Мои Dtos сформированы таким образом, что я также чувствую, что они правильные.
DataGetDto с начальным вложенным Dto:
public class DataGetDto
{
public int ModelId { get; set; }
public IEnumerable<SubSpecialtyDto> SubSpecialtyDto { get; set; }
}
SubSpecialtyDto с дополнительными вложенными Dtos:
public class SubSpecialtyDto
{
[Range(typeof(Decimal), "0", "999999")]
public decimal? CostOp { get; set; } //Not sure
[Range(typeof(Decimal), "0", "999999")]
public decimal? CostTh { get; set; } //Not sure
public int SubSpecialtyTypeId { get; set; }
public int ModelId { get; set; }
public IEnumerable<FacilityActivityDto> FacilityActivityDto { get; set; }
public IEnumerable<OutPatientActivityDto> OutPatientActivityDto { get; set; }
public IEnumerable<OutPatientOperationalFactorDto> OutPatientOperationalFactorDto { get; set; }
public IEnumerable<SkillMixDistributionDto> SkillMixDistributionDto { get; set; }
public IEnumerable<TheatreListStructureDto> TheatreListStructureDto { get; set; }
public IEnumerable<TheatreOperationalFactorDto> TheatreOperationalFactorDto { get; set; }
}
OutPatientActivityDto в качестве примера вложенного Dtos второго уровня:
public class OutPatientActivityDto
{
[Range(0, int.MaxValue)]
public int? PatientsSeenOp { get; set; }
[Range(typeof(Decimal), "0", "999999")]
public decimal? AverageIncomeOp { get; set; }
[Range(typeof(Decimal), "0", "1")]
public decimal? ConversionRate { get; set; }
public int ActivityId { get; set; }
public int SubSpecialtyTypeId { get; set; }
public int PathwayId { get; set; }
public int ModelId { get; set; }
}
Поэтому мои вопросы:
Действительны ли структуры Dto?
Как можно отредактировать метод GetData, чтобы удалить текущую ошибку и правильно отобразить данные?
Если что-то слишком расплывчатое или отсутствует, спросите, и я обязательно добавлю больше информации. Заранее спасибо!
UPDATE
Во время перечитывания моего поста я понял, что для некоторых это может быть полезно, если я приложу диаграмму стиля ERD для ссылки на структуру базы данных здесь .
Ошибка присутствует только при отладке через Watch, нет принудительного исключения, и когда я тестирую код с помощью URL, возвращается пустая страница (я еще не настроил представление, так что это ожидается).
Кажущийся рабочий код ниже с использованием Оптимизация коррелированного подзапроса :
var dto =
_dbContext.ModelVersion
.Where(mv => version == mv.Id)
.Select(mv => new DataGetDto
{
ModelId = mv.Id,
SubSpecialtyDto = mv.SubSpecialties
.Where(ss => ss.ModelId == version && subSpecialty.Contains(ss.SubSpecialtyTypeId))
.Select(ss => new SubSpecialtyDto
{
CostOp = ss.CostOp,
CostTh = ss.CostTh,
ModelId = ss.ModelId,
SubSpecialtyTypeId = ss.SubSpecialtyTypeId,
FacilityActivityDto = mv.FacilityActivities
.Where(fa => fa.ModelId == version && pointOfDelivery.Contains(fa.PointOfDeliveryId) && pathway.Contains(fa.PathwayId) && subSpecialty.Contains(fa.SubSpecialtyTypeId))
.Select(fa => new FacilityActivityDto
{
PatientCases = fa.PatientCases,
AverageIncome = fa.AverageIncome,
CostToBookSinglePatient = fa.CostToBookSinglePatient,
AverageCaseTime = fa.AverageCaseTime,
PoDproportion = fa.PoDproportion,
LengthOfStay = fa.LengthOfStay,
PatientHandlingCost = fa.PatientHandlingCost,
CostPerDay = fa.CostPerDay,
BedOccupancy = fa.BedOccupancy,
InplantCost = fa.InplantCost,
OverHead = fa.OverHead,
ModelId = fa.ModelId,
PointOfDeliveryId = fa.PointOfDeliveryId,
PathwayId = fa.PathwayId,
SubSpecialtyTypeId = fa.SubSpecialtyTypeId
}).ToList(),
OutPatientActivityDto = mv.OutPatientActivities
.Where(opa => opa.ModelId == version && opActivity.Contains(opa.ActivityId) && pathway.Contains(opa.PathwayId) && subSpecialty.Contains(opa.SubSpecialtyTypeId))
.Select(opa => new OutPatientActivityDto
{
PatientsSeenOp = opa.PatientsSeenOp,
AverageIncomeOp = opa.AverageIncomeOp,
ConversionRate = opa.ConversionRate,
ModelId = opa.ModelId,
ActivityId = opa.ActivityId,
PathwayId = opa.PathwayId,
SubSpecialtyTypeId = opa.SubSpecialtyTypeId
}).ToList(),
OutPatientOperationalFactorDto = mv.OutPatientOperationalFactors
.Where(opof => opof.ModelId == version && opActivity.Contains(opof.ActivityId) && subSpecialty.Contains(opof.SubSpecialtyTypeId))
.Select(opof => new OutPatientOperationalFactorDto
{
BookingRateOp = opof.BookingRateOp,
DnarateOp = opof.DnarateOp,
PatientCancellationRateOp = opof.PatientCancellationRateOp,
HospitalCancellationRateOp = opof.HospitalCancellationRateOp,
PatientLateNoticeRateOp = opof.PatientLateNoticeRateOp,
HospitalLateNoticeRateOp = opof.HospitalLateNoticeRateOp,
CostToBookSingleOutPatient = opof.CostToBookSingleOutPatient,
ModelId = opof.ModelId,
ActivityId = opof.ActivityId,
SubSpecialtyTypeId = opof.SubSpecialtyTypeId
}).ToList(),
SkillMixDistributionDto = mv.SkillMixDistributions
.Where(smd => smd.ModelId == version && opActivity.Contains(smd.JobTypeId) && pathway.Contains(smd.PathwayId) && subSpecialty.Contains(smd.SubSpecialtyTypeId))
.Select(smd => new SkillMixDistributionDto
{
WorkingWeeksPerYearOp = smd.WorkingWeeksPerYearOp,
WorkingWeeksPerYearTh = smd.WorkingWeeksPerYearTh,
CostPerPa = smd.CostPerPa,
DistributionOp = smd.DistributionOp,
DistributionTh = smd.DistributionTh,
AdminTimeOp = smd.AdminTimeOp,
SetupTimeOp = smd.SetupTimeOp,
CacheUpTimeOp = smd.CacheUpTimeOp,
PatientFacingTimeOp = smd.PatientFacingTimeOp,
ModelId = smd.ModelId,
JobTypeId = smd.JobTypeId,
PathwayId = smd.PathwayId,
SubSpecialtyTypeId = smd.SubSpecialtyTypeId,
}).ToList(),
TheatreListStructureDto = mv.TheatreListStructures
.Where(tls => tls.ModelId == version && theatreList.Contains(tls.TheatreListTypeId) && pathway.Contains(tls.SubSpecialtyTypeId))
.Select(tls => new TheatreListStructureDto
{
PreOpWardRound = tls.PreOpWardRound,
PostOpWardRound = tls.PostOpWardRound,
FacingPatientTime = tls.FacingPatientTime,
BreakTime = tls.BreakTime,
PreferredSessionType = tls.PreferredSessionType,
ModelId = tls.ModelId,
TheatreListTypeId = tls.TheatreListTypeId,
SubSpecialtyTypeId = tls.SubSpecialtyTypeId
}).ToList(),
TheatreOperationalFactorDto = mv.TheatreOperationalFactors
.Where(tof => tof.ModelId == version && pointOfDelivery.Contains(tof.PointOfDeliveryId) && subSpecialty.Contains(tof.SubSpecialtyTypeId))
.Select(tof => new TheatreOperationalFactorDto
{
CostToRunListTh = tof.CostToRunListTh,
PreOpAnaesthetic = tof.PreOpAnaesthetic,
PostOpAnaesthetic = tof.PostOpAnaesthetic,
KnifeToSkin = tof.KnifeToSkin,
Gaps = tof.Gaps,
LateStart = tof.LateStart,
EarlyFinish = tof.EarlyFinish,
InSessionUtilisation = tof.InSessionUtilisation,
ModelId = tof.ModelId,
PointOfDeliveryId = tof.PointOfDeliveryId,
SubSpecialtyTypeId = tof.SubSpecialtyTypeId
}).ToList()
})
});