如何在ASP.NET中同时填充嵌套对象?
药物时间表:
public int? UserId { get; set; }
public User User { get; set; } = null!;
public int? MedicationId { get; set; }
public Medication Medication { get; set; } = null!;
public int NumberOfPills { get; set; }
public int Duration { get; set; }
public DateOnly StartDate { get; set; }
public DateOnly? EndDate { get; set; }
public List<ReminderPlanning> ReminderPlannings { get; set; } = new List<ReminderPlanning>();
提醒计划(该时间表的每日安排):
public int Id { get; set; }
public DateOnly reminderDay { get; set; }
public string? dayOfWeek { get; set; }
public int? MedicationScheduleId { get; set; }
public MedicationSchedule MedicationSchedule { get; set; } = new MedicationSchedule();
public List<MedicationReminder> medicationReminders { get; set; } = new List<MedicationReminder>();
药物提醒(你希望收到提醒的小时):
public int Id { get; set; }
public int? ReminderPlanningId { get; set; }
public ReminderPlanning? ReminderPlanning { get; set; }
public TimeOnly ReminderHour { get; set; }
我采用了这种架构,让用户可以动态选择提醒次数。
起初我想做的是在每次创建父对象时使用一个循环:
public async Task<MedicationSchedule> CreateMedicationScheduleAsync(MedicationSchedule medicationScheduleModel)
{
medicationScheduleModel.EndDate = medicationScheduleModel.StartDate.AddDays(medicationScheduleModel.Duration);
return await _scheduleRepository.CreateMedicationScheduleAsync(medicationScheduleModel);
// for (int i = 0; i <medicationScheduleModel.duration ; i++) {
// call create planning, and inside that service I would create the reminder
// for (int i = 0; i <medicationPlanningModel.MedicationSchedule.numberofpills; i++) {
// Obviously the order is messed up}
// }
}
但提醒小时并未随时间表一起发送。这迫使我创建一个包含空计划项的时间表,并使用一个单独的POST请求来填充这些表。
编辑:DTO
using backend.Models;
namespace backend.Dtos.MedicationScheduleDtos
{
public class CreateMedicationScheduleDto
{
public int? UserId { get; set; }
public int? MedicationId { get; set; }
public int NumberOfPills { get; set; }
public int Duration { get; set; }
public DateOnly StartDate { get; set; }
public List<CreateReminderPlanningDto> ReminderPlannings { get; set; }
}
}
控制器中的POST方法:
[HttpPost]
public async Task<IActionResult> CreateSchedule([FromBody] CreateMedicationScheduleDto medicationScheduleDto)
{
var medicationScheduleModel = medicationScheduleDto.ToMedicationScheduleFromCreateDto();
await _scheduleService.CreateMedicationScheduleAsync(medicationScheduleModel);
return CreatedAtAction(nameof(GetScheduleById), new { id = medicationScheduleModel.Id }, medicationScheduleModel.ToMedicationScheduleDto());
}
解决方案
你可以在一个单一的POST请求中填充三层结构(MedicationSchedule → ReminderPlanning → MedicationReminder)。当你创建一个对象图并调用 SaveChanges() 时,Entity Framework会为你处理好这一切。
步骤1:在控制器中接收嵌套的JSON
确保你的API支持整个嵌套的数据结构:
[HttpPost]
public async Task<IActionResult> CreateMedicationSchedule([FromBody] MedicationSchedule medicationScheduleModel)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _scheduleService.CreateWithRemindersAsync(medicationScheduleModel);
return CreatedAtAction(nameof(GetSchedule), new { id = result.Id }, result);
}
示例JSON负载 客户端应发送:
{
"userId": 1,
"medicationId": 5,
"numberOfPills": 2,
"duration": 7,
"startDate": "2026-05-01",
"reminderPlannings": [
{
"reminderDay": "2026-05-01",
"dayOfWeek": "Thursday",
"medicationReminders": [
{ "reminderHour": "08:00" },
{ "reminderHour": "20:00" }
]
}
]
}
步骤2:在你的服务中构建并保存整个对象图
public async Task<MedicationSchedule> CreateWithRemindersAsync(MedicationSchedule model)
{
// 1. Calculate end date
model.EndDate = model.StartDate.AddDays(model.Duration);
// 2. Auto-generate daily ReminderPlannings if not provided
if (model.ReminderPlannings == null || !model.ReminderPlannings.Any())
{
for (int i = 0; i < model.Duration; i++)
{
var day = model.StartDate.AddDays(i);
model.ReminderPlannings.Add(new ReminderPlanning
{
reminderDay = day,
dayOfWeek = day.DayOfWeek.ToString(),
medicationReminders = new List<MedicationReminder>()
});
}
}
// 3. Link each planning back to the schedule (EF needs this)
foreach (var planning in model.ReminderPlannings)
{
planning.MedicationSchedule = model;
}
// 4. Add the root entity - EF Core tracks the entire graph
await _context.MedicationSchedules.AddAsync(model);
// 5. ONE SaveChanges() inserts everything in a single transaction [[8]][[16]]
await _context.SaveChangesAsync();
return model;
}
步骤3:验证你的实体配置
确保你的关系在 OnModelCreating 中正确设置:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MedicationSchedule>()
.HasMany(s => s.ReminderPlannings)
.WithOne(p => p.MedicationSchedule)
.HasForeignKey(p => p.MedicationScheduleId)
.OnDelete(DeleteBehavior.Cascade); // Optional: auto-delete children if parent is deleted
modelBuilder.Entity<ReminderPlanning>()
.HasMany(p => p.medicationReminders)
.WithOne(r => r.ReminderPlanning)
.HasForeignKey(r => r.ReminderPlanningId)
.OnDelete(DeleteBehavior.Cascade);
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。