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

使用FirstOrDefault获取嵌套查询首元素无返回问题排查

问题诊断与解决方案

1. 核心问题:关联数据未正确加载

你的Trip.TripStations为空,大概率是因为Entity Framework没有显式加载关联的TripStation数据。默认情况下EF使用延迟加载,但如果视图渲染时DbContext已被释放,延迟加载会失败,导致TripStations为null或空集合。

解决方法:
查询Trip时,用Include和ThenInclude显式加载所有关联数据:

// 替换Index.cshtml.cs中的查询代码
Trip trip = TripD.Trips
    .Include(t => t.TripStations) // 加载Trip关联的TripStation集合
    .ThenInclude(ts => ts.Station) // 进一步加载TripStation关联的Station
    .Where(i => i.ID == id.Value)
    .Single();

2. 修正Index.cshtml.cs中的错误代码

当前代码存在两处明显错误:

  • 重复查询同一个Trip,完全冗余
  • TripD.TripStations = (IEnumerable<TripStation>) trip.TripStations.Select(s => s.Station); 类型转换错误:Select(s=>s.Station)返回IEnumerable<Station>,强制转成IEnumerable<TripStation>会导致类型不匹配,后续使用必然出错。

修正后的代码:

if (id != null)
{
    TripID = id.Value;
    // 一次性加载所有需要的关联数据
    Trip trip = TripD.Trips
        .Include(t => t.TripStations)
        .ThenInclude(ts => ts.Station)
        .Include(t => t.TripCategories)
        .ThenInclude(tc => tc.Category)
        .Where(i => i.ID == id.Value)
        .Single();
    
    TripD.Categories = trip.TripCategories.Select(s => s.Category);
    TripD.TripStations = trip.TripStations; // 直接赋值TripStation集合,无需转换
}

3. 视图中处理空引用风险

即使加载了数据,TripStations可能为空或元素不足,直接调用FirstOrDefault().Station.Name会引发空引用异常,需添加空值判断:

表头部分修正:

<dd>@(Model.Trip.Any() && Model.Trip[0].TripStations.Any() 
    ? Html.DisplayNameFor(model => model.Trip[0].TripStations.First().Station.Name) 
    : "From")</dd>
@(Model.Trip.Any() && Model.Trip[0].TripStations.Any() 
    ? Html.DisplayNameFor(model => model.Trip[0].TripStations.Last().Station.Name) 
    : "To")

表格内容部分修正:

<td>
    @(item.TripStations?.FirstOrDefault()?.Station?.Name ?? "N/A")
</td>
<td>
    @(item.TripStations?.LastOrDefault()?.Station?.Name ?? "N/A")
</td>

4. 修正TripStationUtilities中的潜在问题

你的MoveStations方法存在两个风险:

  • 如果l元素数量小于2,Skip(1).First()会抛出异常
  • 直接修改传入的ICollection可能引发集合修改异常(比如集合是只读的)

修正后的方法:

public ICollection<TripStation> MoveStations(ICollection<TripStation> l)
{
    if (l?.Count < 2)
        return l; // 元素不足时直接返回原集合
    
    // 转成List避免修改原集合的问题
    var stationList = l.ToList();
    var toStation = stationList.Skip(1).First();
    stationList.Remove(toStation);
    stationList.Add(toStation);
    
    return stationList;
}

额外建议:为Trip添加计算属性(可选)

如果不想每次在视图里写复杂空判断,可以在Trip模型中添加计算属性,简化视图代码:

public class Trip
{
    // 其他属性...
    public ICollection<TripStation>? TripStations { get; set; }

    // 若TripStation有排序字段(如OrderIndex),建议用对应字段排序,保证顺序正确
    public string? FromStationName => TripStations?.OrderBy(ts => ts.ID).FirstOrDefault()?.Station?.Name;
    public string? ToStationName => TripStations?.OrderBy(ts => ts.ID).LastOrDefault()?.Station?.Name;
}

视图中直接使用:

<td>@Html.DisplayFor(modelItem => item.FromStationName)</td>
<td>@Html.DisplayFor(modelItem => item.ToStationName)</td>

内容的提问来源于stack exchange,提问作者Tudor Ilisiu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:02:45