You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

订单创建时加载可用Trailer下拉框及状态更新异常求助

问题分析与解决方案

Let's break down the issues in your code and fix them step by step to get your trailer selection working properly:

核心问题排查

  • Include方法误用:你在Add() GET方法里写的Include(c => c.TrailerStatus == "Avaliable")是完全错误的。Include的作用是加载EF实体的关联导航属性(比如你的orderforTrailer),而不是过滤数据。过滤可用拖车应该用Where条件,这是导致程序崩溃的直接原因。
  • 拼写错误:状态值里的Avaliable(正确拼写是Available)、Unavilable(正确拼写是Unavailable)存在拼写错误,会导致状态判断失效,拖车永远不会被标记为不可用。
  • 重复查询浪费性能:在HttpPost方法里你两次查询同一个Trailer,既冗余又浪费数据库资源。
  • 类级别变量的线程安全风险:你在类外部声明Trailer trailerSelected = new Trailer();,这会导致多并发请求时的数据混乱,应该在方法内部声明变量。
  • 一对一关系未明确配置:EF Core默认可能会把你的TrailerOrder的导航属性识别为一对多关系,需要显式配置才能确保一对一约束生效。

修正后的代码

1. 实体类(修正拼写+引入常量避免错误)

// 把状态值定义为常量,彻底避免拼写错误
public static class StatusConstants
{
    public const string Available = "Available";
    public const string Unavailable = "Unavailable";
}

public class Trailer
{
    public string SerialNumber { get; set; }
    public string TrailerNumber { get; set; }
    public string TrailerStatus { get; set; }
    public int TrailerID { get; set; }

    // 一对一关系导航属性(规范命名)
    public virtual Order OrderForTrailer { get; set; }

    public Trailer()
    {
        TrailerStatus = StatusConstants.Available;
    }
}

public class Order
{
    public string OrderNumber { get; set; }
    public string OrderStatus { get; set; }
    public int OrderID { get; set; }

    // 一对一关系导航属性(规范命名)
    public virtual Trailer TrailerForLoad { get; set; }

    public Order()
    {
        OrderStatus = StatusConstants.Available;
    }
}

2. GET方法(修正过滤逻辑)

public IActionResult Add()
{
    // 用Where过滤可用拖车,不需要的关联属性可以不用Include
    var availableTrailers = context.Trailers
                                   .Where(t => t.TrailerStatus == StatusConstants.Available)
                                   .ToList();

    var addOrderViewModel = new AddOrderViewModel(availableTrailers);
    return View(addOrderViewModel);
}

3. HttpPost方法(优化查询+修正状态+移除风险变量)

[HttpPost]
public IActionResult Add(AddOrderViewModel addOrderViewModel)
{
    if (!ModelState.IsValid)
    {
        // 验证失败时重新加载可用拖车,避免下拉菜单为空
        addOrderViewModel.AvailableTrailers = context.Trailers
                                                     .Where(t => t.TrailerStatus == StatusConstants.Available)
                                                     .ToList();
        return View(addOrderViewModel);
    }

    // 一次查询获取选中的拖车,用FirstOrDefault避免找不到时抛出异常
    var selectedTrailer = context.Trailers
                                 .FirstOrDefault(t => t.TrailerID == addOrderViewModel.TrailerID);

    if (selectedTrailer == null)
    {
        ModelState.AddModelError("TrailerID", "Selected trailer does not exist.");
        addOrderViewModel.AvailableTrailers = context.Trailers
                                                     .Where(t => t.TrailerStatus == StatusConstants.Available)
                                                     .ToList();
        return View(addOrderViewModel);
    }

    // 创建新订单并关联拖车
    var newOrder = new Order
    {
        OrderNumber = addOrderViewModel.OrderNumber,
        TrailerForLoad = selectedTrailer
    };

    // 标记拖车为不可用
    selectedTrailer.TrailerStatus = StatusConstants.Unavailable;

    context.Orders.Add(newOrder);
    context.SaveChanges();

    return Redirect("/Order");
}

4. DbContext中配置一对一关系(关键)

在你的DbContext的OnModelCreating方法中添加以下配置,确保EF Core正确识别一对一关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>()
                .HasOne(o => o.TrailerForLoad)
                .WithOne(t => t.OrderForTrailer)
                .HasForeignKey<Order>(o => o.OrderID); // 可根据你的实际外键配置调整,这里假设OrderID作为关联外键
}

额外建议

  • 使用异步方法(比如ToListAsync()FirstOrDefaultAsync()SaveChangesAsync())来提升Web应用的并发处理能力。
  • 给实体类属性添加必要的数据注解(比如[Required][Key]),确保EF Core正确识别主键和必填字段。
  • 确认你的AddOrderViewModelTrailerID属性已正确绑定到下拉菜单的选项值,避免提交时出现值不匹配的问题。

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

火山引擎 最新活动