You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:24:57