【问题标题】:C# - Retrieve data from persistence storage and save it to the view modelC# - 从持久存储中检索数据并将其保存到视图模型
【发布时间】:2020-07-07 16:57:16
【问题描述】:

您好,我有一个控制器方法,我想返回看起来像这样的视图模型

这是硬编码后的样子

 public ActionResult SpecialOrderSummary(int? id)
        {
            // Retrieve data from persistence storage and save it to the view model.
            // But here I am just faking it.
            var vm = new ItemViewModel
            {
                ItemId = 123,
                ItemName = "Fake Item",
                Parts = new List<ItemPartViewModel>
                {
                    new ItemPartViewModel
                    {
                        PartId = 1,
                        PartName = "Part 1"
                    },
                    new ItemPartViewModel
                    {
                        PartId = 2,
                        PartName = "Part 2"
                    }
                }
            };

            return View(vm);
        }

但我显然不希望它被硬编码。所以这就是我试图做的,而不是实现我的目标

  public ActionResult SpecialOrderSummary(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            JobOrder jobOrder = db.JobOrders.Find(id);
            if (jobOrder == null)
            {
                return HttpNotFound();
            }
            ViewBag.JobOrderID = jobOrder.ID;
            ItemInstance ii = db.ItemInstances.Where(x => x.serialNumber == jobOrder.serialNumber).FirstOrDefault();
            Item item = db.Items.Find(ii.ItemID);

            var vm = new ItemViewModel
            {
                ItemId = item.ItemID,
                ItemName = item.Name,
                Parts = new List<ItemPartViewModel>
                {
                  foreach(ItemHasParts ihp in item.IHP) 
                   {
                     Part part = db.Parts.Find(ihp.PartID);
                     new ItemPartViewModel
                     {
                        PartId = part.ID,
                        PartName = part.Name
                     };
                   }
                }
             };

            return View(vm);
        }

但这不起作用。因为它似乎无法识别结束 } 开头的“零件”和开头的“vm”括号,因为它跳过了两者。这是为什么呢?

【问题讨论】:

  • 这会以什么方式失败?这是使用调试器单步执行代码并观察其确切行为的好机会。有错误吗?意想不到的结果?还有什么?
  • 对不起,我会添加错误消息。我刚刚得到了一些红线,所以我认为我只是做错了@David
  • @David 现在只是不认识开头部分 { 的结尾 }。它关闭了方法,而不是关闭“部分”。而不是关闭“vm”,而是关闭整个控制器。似乎它只是忽略了 vm 和打开的部分 {
  • 您可能只是在某处缺少括号或分号。您的第一个示例在上面缺少一个。
  • @Nikki9696 哎呀,这只是一个复制和粘贴错误。但无论如何,问题出在第二个例子上。你看到什么了吗?

标签: c# asp.net-mvc model viewmodel


【解决方案1】:

嗯,我以为我以前回答过这个问题:https://stackoverflow.com/a/62782124/2410655。基本上你不能在视图模型中间有这样的 for 循环。

我想再添加两件事。

1。身份证?

如果特殊订单摘要需要一个 ID,请不要将其声明为可选。如果这样做,则必须添加更多逻辑来检查是否有 ID。

如果订单摘要需要一个 ID,只需将其声明为 int id。如果客户端不提供,让 MVC 框架处理错误。现在,根据您的设置,您的 MVC 可能会抛出 404、500 或用户友好的页面。由开发者自己来设置。

2。小心 NullReference 异常

在您的代码示例中,我看到您在项目实例上使用了FirstOrDefault()。如果它返回为 NULL 并且您调用 db.Items.Find(ii.ItemID)...


因此,根据您的示例,我将代码更改为:

public ActionResult SpecialOrderSummary(int id)
{
    JObOrder jobOrder = db.JobOrders.Find(id);
    if (jobOrder == null)
    {
        return HttpNotFound();
    }

    ItemInstance itemInstance = db.ItemInstances
        .Where(x => x.serialNumber == jobOrder.serialNumber)
        .FirstOrDefault();

    Item item = null;
    if (itemInstance != null)
    {
        item = db.Items.Find(itemInstance.ItemID);
    }

    var vm = new JobOrderSummaryViewModel
    {
        JobOrderId = jobOrder.ID,
        Parts = new List<ItemPartViewModel>();
    };

    if (item != null)
    {
        vm.ItemId = item.ItemId;
        vm.ItemName = item.ItemName;

        foreach(ItemHasParts ihp in item.IHP) 
        {
            // Does Part and Item have many-to-many relationships?
            // If so, you might be able to get the part by
            // ihp.Part instead of looking it up using the ID.
            // Again, it depends on your setup.
            Part part = db.Parts.Find(ihp.PartID);

            if (part != null)
            {
                vm.Parts.Add(new ItemPartViewModel
                {
                    PartId = part.ID,
                    PartName = part.Name
                });
            }
        }
    }

    return View(vm);
}

注意:

您在循环 (db.Parts.Find(ihp.PartID);) 内还有对数据库的额外调用。如果您有大量数据,这将导致性能问题。有什么方法可以在开始时一次性获取所有需要的数据?

【讨论】:

  • 是的,大卫,你做到了。谢谢!当时我没有回复,所以我有类似的问题,只是措辞略有不同,也许是为了吸引更多人或更清楚。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
  • 2014-03-21
  • 1970-01-01
相关资源
最近更新 更多