c# - C# - 从持久存储中检索数据并将其保存到视图模型
问题描述
你好我有一个控制器方法,我想返回看起来像这样的视图模型
如果它是硬编码的,这就是它的样子
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);
}
但这不起作用。因为它似乎无法识别}
打开的“Parts”和打开的“vm”括号的关闭,因为它跳过了两者。为什么是这样?
解决方案
嗯,我以为我之前回答过这个问题:https ://stackoverflow.com/a/62782124/2410655 。基本上你不能在视图模型中间有这样的 for 循环。
我想再添加两件事。
1.身份证?
如果特殊订单摘要需要一个 ID,请不要将其声明为可选。如果这样做,则必须添加更多逻辑来检查是否有 ID。
如果订单摘要需要一个 ID,只需将其声明为int id
. 如果客户端不提供,让 MVC 框架处理错误。现在,根据您的设置,您的 MVC 可能会抛出 404、500 或用户友好的页面。由开发人员来设置它。
2.注意NullReference Exception
在您的代码示例中,我看到您FirstOrDefault()
在 item 实例上使用过。如果它返回为 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);
您在循环 ( )内还有对数据库的额外调用。如果您有大量数据,这将导致性能问题。有什么方法可以让你一开始就获取你需要的所有数据吗?
推荐阅读
- vue.js - 在 Vuetify 中不工作时,没有使用动态时间选择器填充时间
- javascript - 如果语句不起作用并且未定义
- qml - 滚动条不显示
- console-application - 谁能帮我获取 URL(使用控制台应用程序的查询字符串?)
- javascript - 如何按年份对日期数组进行分组并减去最后一个值 - 第一个值?
- sympy - sympy:请告诉我如何 Point3D 矩阵
- internet-explorer-11 - IE兼容模式下如何判断是IE11还是Edge
- java - 如何从另一个类更新按钮可见性?
- javascript - 我想从一个连续发送多行信息的脚本中实时获取所有回报
- php - Laravel 会话问题 - 覆盖现有会话密钥