ASP.NET MVC中实现航班与预订关联的方案咨询
实现思路与步骤
1. 优化实体关联逻辑
当前Flight和Reservation是多对多关联,但从航班预订的业务场景看,更合理的是一对多关联(一个航班对应多个预订,一个预订归属单个航班),这样数据结构更简洁,贴合常规业务逻辑。若确实需要支持一个用户预订多个航班,可保留多对多,但以下按主流场景调整:
调整Reservation模型
public class Reservation { [Key] public int Id { get; set; } // 原有属性保留 public string FirstName { get; set; } public string SecondName { get; set; } public string LastName { get; set; } public string PersonalID { get; set; } public string PhoneNumber { get; set; } public string Nationality { get; set; } public TicketType TicketType { get; set; } public string Email { get; set; } // 添加外键关联航班 public int FlightId { get; set; } // 导航属性 public virtual Flight Flight { get; set; } public Reservation() { // 移除原多对多的导航属性初始化 } }
调整Flight模型(保留预订集合导航)
public class Flight { [Key] public int Id { get; set; } // 原有属性保留... // 保留航班对应的预订集合 public virtual HashSet<Reservation> Reservations { get; set; } public Flight() { Reservations = new HashSet<Reservation>(); } }
2. 更新数据库结构
修改模型后,生成并执行EF迁移,同步SQL Server数据库:
Add-Migration AddFlightReservationForeignKey Update-Database
3. 修改预订控制器,关联特定航班
GET方法:接收航班ID并传递给视图
// GET: Reservations/Create?flightId=1 public async Task<IActionResult> Create(int flightId) { var flight = await _context.Flights.FindAsync(flightId); if (flight == null) { return NotFound(); } // 将航班ID和基础信息传递给视图 ViewBag.FlightId = flightId; ViewBag.FlightInfo = $"{flight.LocationFrom} → {flight.LocationTo} ({flight.DepartureDate:yyyy-MM-dd HH:mm})"; return View(); }
POST方法:绑定航班ID,处理余票校验与关联
// POST: Reservations/Create [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("Id,FirstName,SecondName,LastName,PersonalID,PhoneNumber,Nationality,TicketType,Email,FlightId")] Reservation reservation) { if (ModelState.IsValid) { var flight = await _context.Flights.FindAsync(reservation.FlightId); if (flight == null) { ModelState.AddModelError("", "对应的航班不存在"); return View(reservation); } // 根据票型校验余票 if (reservation.TicketType == TicketType.Economy && flight.AvailableSeats <= 0) { ModelState.AddModelError("", "经济舱已无余票"); return View(reservation); } if (reservation.TicketType == TicketType.Business && flight.AvailableSeatsBusinessClass <= 0) { ModelState.AddModelError("", "商务舱已无余票"); return View(reservation); } // 扣除对应舱位余票 if (reservation.TicketType == TicketType.Economy) { flight.AvailableSeats--; } else { flight.AvailableSeatsBusinessClass--; } _context.Update(flight); // 添加预订记录 _context.Add(reservation); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(reservation); }
4. 修改预订视图,传递航班ID
在Create.cshtml中添加隐藏字段,自动传递航班ID:
@model Reservation <h1>预订航班</h1> <p>当前预订航班:@ViewBag.FlightInfo</p> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <!-- 原有乘客信息表单字段保留 --> <div class="form-group"> <label asp-for="FirstName" class="control-label"></label> <input asp-for="FirstName" class="form-control" /> <span asp-validation-for="FirstName" class="text-danger"></span> </div> <!-- 其他乘客信息字段... --> <!-- 隐藏字段传递航班ID --> <input type="hidden" asp-for="FlightId" value="@ViewBag.FlightId" /> <div class="form-group"> <input type="submit" value="确认预订" class="btn btn-primary" /> </div> </form>
5. 航班详情页展示所有预订
修改Flight控制器的Details方法,加载关联预订
// GET: Flights/Details/5 public async Task<IActionResult> Details(int? id) { if (id == null) { return NotFound(); } // 加载航班关联的所有预订数据 var flight = await _context.Flights .Include(f => f.Reservations) .FirstOrDefaultAsync(m => m.Id == id); if (flight == null) { return NotFound(); } return View(flight); }
修改航班详情视图,添加预订列表
在Details.cshtml中追加预订展示区域:
@model Flight <h1>航班详情</h1> <!-- 原有航班信息展示区域保留 --> <div> <h4>航班信息</h4> <hr /> <dl class="row"> <dt class="col-sm-2">出发地</dt> <dd class="col-sm-10">@Model.LocationFrom</dd> <dt class="col-sm-2">目的地</dt> <dd class="col-sm-10">@Model.LocationTo</dd> <!-- 其他航班字段... --> </dl> </div> <!-- 预订记录展示 --> <div class="mt-4"> <h4>该航班预订记录</h4> <table class="table"> <thead> <tr> <th>乘客姓名</th> <th>证件号</th> <th>票型</th> <th>联系邮箱</th> </tr> </thead> <tbody> @foreach (var reservation in Model.Reservations) { <tr> <td>@reservation.FirstName @reservation.LastName</td> <td>@reservation.PersonalID</td> <td>@reservation.TicketType</td> <td>@reservation.Email</td> </tr> } </tbody> </table> </div> <div> <a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-primary">编辑航班</a> <a asp-action="Index" class="btn btn-secondary">返回航班列表</a> <a asp-action="Create" controller="Reservations" asp-route-flightId="@Model.Id" class="btn btn-success">预订该航班</a> </div>
6. 航班列表页添加详情入口
在航班列表视图Index.cshtml中,给每个航班添加详情按钮:
@model IEnumerable<Flight> <h1>航班列表</h1> <table class="table"> <thead> <tr> <th>航线</th> <th>出发时间</th> <th>操作</th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td>@item.LocationFrom → @item.LocationTo</td> <td>@item.DepartureDate.ToString("yyyy-MM-dd HH:mm")</td> <td> <a asp-action="Details" asp-route-id="@item.Id" class="btn btn-info">查看详情</a> </td> </tr> } </tbody> </table>
内容的提问来源于stack exchange,提问作者Dex
相关产品推荐
相关产品推荐

