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

如何在Equipment创建视图中同步处理关联Location表的字段录入

问题背景

我的数据库架构中,Location表关联了Floor、Room、Rack三个表,Equipment表关联Location和EquipmentStatus表。

对应的实体类代码如下:

Equipment.cs

public class Equipment
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [DisplayName("Serial Number")]
    public string Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public int Amount { get; set; }

    public int EquipmentStatusId { get; set; }
    [ValidateNever]
    public EquipmentStatus? EquipmentStatus { get; set; }

    public int LocationId { get; set; }
    [ValidateNever]
    public Location? Location { get; set; }

    [Required]
    [DisplayName("Internal or Consigned")]
    public string InternalOrConsigned { get; set; }

    [DisplayName("EOL Date")]
    public DateTime? EOLDate { get; set; }

    public string? EOLDescription { get; set; }
    [ValidateNever]
    [DisplayName("Image")]
    public string? ImageUrl { get; set; }
}

Location.cs

public class Location
{
    [Key]
    public int Id { get; set; }

    public int FloorId { get; set; }
    [ValidateNever]
    public Floor? Floor { get; set; }

    public int RoomId { get; set; }
    [ValidateNever]
    public Room? Room { get; set; }

    public int RackId { get; set; }
    [ValidateNever]
    public Rack? Rack { get; set; }

    [Required]
    public string Row { get; set; }
}

我希望在Equipment的Create.cshtml视图中完成所有属性的录入,已经掌握用SelectListItem处理EquipmentStatusId的下拉选择,但Location关联多个表且包含多属性,不清楚如何处理LocationId的录入。

当前EquipmentsTestController.cs的Create方法代码:

// GET: User/EquipmentsTest/Create
public IActionResult Create()
{
    ViewData["EquipmentStatusId"] = new SelectList(_context.EquipmentStatuses, "Id", "Name");
    ViewData["LocationId"] = new SelectList(_context.Locations, "Id", "Row");
    return View();
}

// POST: User/EquipmentsTest/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Equipment equipment)
{
    if (ModelState.IsValid)
    {
        _context.Add(equipment);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    ViewData["EquipmentStatusId"] = new SelectList(_context.EquipmentStatuses, "Id", "Name", equipment.EquipmentStatusId);
    ViewData["LocationId"] = new SelectList(_context.Locations, "Id", "Row", equipment.LocationId);
    return View(equipment);
}

当前Create.cshtml代码:

<form asp-action="Create">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Id" class="control-label"></label>
        <input asp-for="Id" class="form-control" />
        <span asp-validation-for="Id" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Name" class="control-label"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Amount" class="control-label"></label>
        <input asp-for="Amount" class="form-control" />
        <span asp-validation-for="Amount" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="EquipmentStatusId" class="control-label"></label>
        <select asp-for="EquipmentStatusId" class ="form-control" asp-items="ViewBag.EquipmentStatusId"></select>
    </div>
    <div class="form-group">
        <label asp-for="LocationId" class="control-label"></label>
        <select asp-for="LocationId" class ="form-control" asp-items="ViewBag.LocationId"></select>
    </div>
    <div class="form-group">
        <label asp-for="InternalOrConsigned" class="control-label"></label>
        <input asp-for="InternalOrConsigned" class="form-control" />
        <span asp-validation-for="InternalOrConsigned" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="EOLDate" class="control-label"></label>
        <input asp-for="EOLDate" class="form-control" />
        <span asp-validation-for="EOLDate" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="EOLDescription" class="control-label"></label>
        <input asp-for="EOLDescription" class="form-control" />
        <span asp-validation-for="EOLDescription" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="ImageUrl" class="control-label"></label>
        <input asp-for="ImageUrl" class="form-control" />
        <span asp-validation-for="ImageUrl" class="text-danger"></span>
    </div>
    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

解决方案

有两种常见处理方式,根据业务需求选择:

方案1:选择已存在的Location(优化下拉选项可读性)

当前代码中Location的下拉仅显示Row字段,用户无法明确该位置的完整信息。可以修改SelectList的显示文本,拼接关联的Floor、Room、Rack名称,让用户清晰选择。

修改Controller代码

在GET和POST方法中,更新ViewData["LocationId"]的赋值:

ViewData["LocationId"] = new SelectList(
    _context.Locations
        .Include(l => l.Floor)
        .Include(l => l.Room)
        .Include(l => l.Rack),
    "Id",
    l => $"{l.Floor.Name} - {l.Room.Name} - {l.Rack.Name} - 行:{l.Row}"
);

注意:需确保Floor、Room、Rack实体类包含Name属性,若属性名不同需对应修改。

View代码无需修改

保持原有的select控件即可,提交后LocationId会自动绑定到Equipment实体,直接保存即可。


方案2:创建Equipment时同时新建Location

如果业务需要在添加设备时直接录入新的位置信息,而非选择已有位置,需通过ViewModel实现:

步骤1:创建ViewModel

定义包含Equipment和Location所有字段的ViewModel:

public class EquipmentCreateViewModel
{
    // Equipment属性
    public string Id { get; set; }
    public string Name { get; set; }
    public int Amount { get; set; }
    public int EquipmentStatusId { get; set; }
    public string InternalOrConsigned { get; set; }
    public DateTime? EOLDate { get; set; }
    public string? EOLDescription { get; set; }
    public string? ImageUrl { get; set; }

    // Location属性
    public int FloorId { get; set; }
    public int RoomId { get; set; }
    public int RackId { get; set; }
    public string Row { get; set; }
}

步骤2:修改Controller代码

GET方法:传递关联表的下拉数据

public IActionResult Create()
{
    ViewData["EquipmentStatusId"] = new SelectList(_context.EquipmentStatuses, "Id", "Name");
    ViewData["FloorId"] = new SelectList(_context.Floors, "Id", "Name");
    ViewData["RoomId"] = new SelectList(_context.Rooms, "Id", "Name");
    ViewData["RackId"] = new SelectList(_context.Racks, "Id", "Name");
    return View();
}

POST方法:先保存Location,再关联Equipment

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(EquipmentCreateViewModel vm)
{
    if (ModelState.IsValid)
    {
        // 创建并保存新Location
        var newLocation = new Location
        {
            FloorId = vm.FloorId,
            RoomId = vm.RoomId,
            RackId = vm.RackId,
            Row = vm.Row
        };
        _context.Locations.Add(newLocation);
        await _context.SaveChangesAsync();

        // 创建Equipment并关联新Location的Id
        var newEquipment = new Equipment
        {
            Id = vm.Id,
            Name = vm.Name,
            Amount = vm.Amount,
            EquipmentStatusId = vm.EquipmentStatusId,
            LocationId = newLocation.Id,
            InternalOrConsigned = vm.InternalOrConsigned,
            EOLDate = vm.EOLDate,
            EOLDescription = vm.EOLDescription,
            ImageUrl = vm.ImageUrl
        };
        _context.Equipments.Add(newEquipment);
        await _context.SaveChangesAsync();

        return RedirectToAction(nameof(Index));
    }

    // 验证失败时重新加载下拉数据
    ViewData["EquipmentStatusId"] = new SelectList(_context.EquipmentStatuses, "Id", "Name", vm.EquipmentStatusId);
    ViewData["FloorId"] = new SelectList(_context.Floors, "Id", "Name", vm.FloorId);
    ViewData["RoomId"] = new SelectList(_context.Rooms, "Id", "Name", vm.RoomId);
    ViewData["RackId"] = new SelectList(_context.Racks, "Id", "Name", vm.RackId);
    return View(vm);
}

步骤3:修改Create.cshtml视图

替换原有的LocationId下拉控件为Location的各个字段输入:

<form asp-action="Create">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    
    <!-- Equipment原有字段保持不变 -->
    <div class="form-group">
        <label asp-for="Id" class="control-label"></label>
        <input asp-for="Id" class="form-control" />
        <span asp-validation-for="Id" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Name" class="control-label"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Amount" class="control-label"></label>
        <input asp-for="Amount" class="form-control" />
        <span asp-validation-for="Amount" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="EquipmentStatusId" class="control-label"></label>
        <select asp-for="EquipmentStatusId" class="form-control" asp-items="ViewBag.EquipmentStatusId"></select>
    </div>
    <div class="form-group">
        <label asp-for="InternalOrConsigned" class="control-label"></label>
        <input asp-for="InternalOrConsigned" class="form-control" />
        <span asp-validation-for="InternalOrConsigned" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="EOLDate" class="control-label"></label>
        <input asp-for="EOLDate" class="form-control" />
        <span asp-validation-for="EOLDate" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="EOLDescription" class="control-label"></label>
        <input asp-for="EOLDescription" class="form-control" />
        <span asp-validation-for="EOLDescription" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="ImageUrl" class="control-label"></label>
        <input asp-for="ImageUrl" class="form-control" />
        <span asp-validation-for="ImageUrl" class="text-danger"></span>
    </div>

    <!-- 新增Location字段输入 -->
    <div class="form-group">
        <label asp-for="FloorId" class="control-label"></label>
        <select asp-for="FloorId" class="form-control" asp-items="ViewBag.FloorId"></select>
    </div>
    <div class="form-group">
        <label asp-for="RoomId" class="control-label"></label>
        <select asp-for="RoomId" class="form-control" asp-items="ViewBag.RoomId"></select>
    </div>
    <div class="form-group">
        <label asp-for="RackId" class="control-label"></label>
        <select asp-for="RackId" class="form-control" asp-items="ViewBag.RackId"></select>
    </div>
    <div class="form-group">
        <label asp-for="Row" class="control-label"></label>
        <input asp-for="Row" class="form-control" />
        <span asp-validation-for="Row" class="text-danger"></span>
    </div>

    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:05:48