我正在尝试学习ASP.Net Core,并且在弄清楚如何以MVC'样式'(?)移动数据时遇到了麻烦。我正在关注的Microsoft网站上的ASP.NET Core教程不涉及模型之间的任何关系。 (似乎是愚蠢的疏忽?)也许我的Google-Fu已关闭,所以如果这很明显,或者任何人有我可以为ASPNETCore查看的阅读材料,我将不胜感激。
我有两个模型。一个称为Device,另一个称为DeviceType。
在我的设备模型中,我有对DeviceType属性的引用。
public class Device{
[Key]
public int ID {get; set;}
[Required]
[Display(Name = "Device Name")]
public String deviceName {get; set;}
[Required]
[Display(Name="Description")]
public String deviceDescription {get; set;}
[Required]
[Display(Name="Type")]
public DeviceType deviceType{get; set;}
}
public class DeviceType{
[Key]
public int ID {get; set;}
[Required]
[Display(Name="Type")]
public String name {get;set;}
[Required]
[Display(Name="Description")]
public String description {get;set;}
}
我想弄清楚如何-对于每个操作(CRUD)-引用并获取特定Device对象的deviceType。当我在视图上工作时,我也不理解如何引用相关的设备类型。
获取创建
*如何获取我的DeviceTypes的SelectList,以便用户可以创建设备并选择设备的类型?
*我已经对View部分进行了一些研究,看起来我需要使用速记式Razor“ @ model.SelectList()”语法,但是参数对我来说很混乱。我不完全了解它的要求。这是该操作器当前的外观。
public IActionResult Create()
{
return View();
}
指数
*在显示所有设备的循环中,如何将设备类型的名称也包含在结果设备表中?
*在视图中,我假设可以使用@ Html.LabelFor来显示数据的名称,但是如何获取实际值?
public async Task<IActionResult> Index()
{
return View(await _context.Device.ToListAsync());
}
更新/编辑
*如何检索设备对象的设备类型,然后允许用户对其进行编辑?
// GET: Devices/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var device = await _context.Device.SingleOrDefaultAsync(m => m.ID == id);
if (device == null)
{
return NotFound();
}
return View(device);
}
删除
*我还没有看过这个,但是我把它放在这里是为了防止在编写其他动作时有任何警告...
// GET: Devices/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var device = await _context.Device
.SingleOrDefaultAsync(m => m.ID == id);
if (device == null)
{
return NotFound();
}
return View(device);
}
再说一次,如果除了微软的“用Mac和Linux和Visual Studio Code构建Linux的asp.net核心应用程序”之外,我还有其他资源可以参考,那将解释如何在视图/控制器内部引用模型中的关系。很棒。
谢谢
最佳答案
首先,我假设在这里使用实体框架,因为这是迄今为止最常见的设置。
取得deviceType
借助EF,可以延迟,热切或显式加载关系。延迟加载是自动驾驶仪的方法:当您需要时,数据就神奇地出现在这里。但是,为了启用延迟加载,该属性必须为virtual
。这是因为EF必须重写该属性才能向其添加延迟加载逻辑,并且如果该属性不是虚拟的,则EF不能这样做。
public virtual DeviceType deviceType{get; set;}
或者,您可以渴望或明确加载您的关系。显式加载几乎具有延迟加载的所有弊端,而没有任何优点,因此不建议您这样做,除非您出于特定原因这么做。不过,您可以通过以下方式实现这一目标:
context.Entry(device).Reference(m => m.deviceType).Load();
最后,您可以急于加载关系,但是必须与初始查询一起完成(因此称为“急切”)。
var devices = context.Devices.Include(m => m.deviceType);
如果不执行这些操作之一,则您的关系属性将为
null
。创建设备类型的下拉列表
在您看来,您显然很想使用
Html.DropDownListFor
。但是,您有一个问题,因为您在Device
上没有要绑定的属性。 select
的发布值将是一个简单的类型,例如整数id,因此您不能将其直接绑定到deviceType
之类的属性。您有两种选择:将一个属性添加到
Device
作为外键,而不是依赖于EF创建的隐式:public int deviceTypeId { get; set; }
创建具有上述属性的视图模型。发布后,您将把视图模型中的值映射到您的实体上,当涉及到
deviceTypeId
时,将使用该值从数据库中提取适当的设备类型,然后使用以下命令在您的实体上设置deviceType
那。接下来,您将需要一个IEnumerable
. Don't bother creating an actual
SelectList`实例。 Razor可以解决这个问题,并且只要让Razor处理它,事情通常会更加顺利。创建起来很简单:ViewBag.DeviceTypeOptions = context.DeviceTypes.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.Name
});
然后,在您看来:
@Html.DropDownListFor(m => m.deviceTypeId, (IEnumerable<SelectListItem>)ViewBag.DeviceTypeOptions)
如果确实使用视图模型,而不是直接使用实体,则最好将选项放在视图模型上,而不要使用
ViewBag
,但是您可以通过任何一种方式完成工作。获取
deviceType
名称LabelFor
用于生成实际的HTML label
。假设DeviceType
具有属性Name
,结果将是:<label for="Name">Name</label>
在内部,
LabelFor
将调用DisplayNameFor
,这是您获取属性的实际名称(或Display
属性中的值)的方式。结果就是:Name
您要查找的是
DisplayFor
或仅是@
语法。以下在功能上等效,并且都将输出类似Some Awesome Device Type
的内容:@Html.DisplayFor(m => m.Name)
@Model.Name
编辑
deviceType
对于Stack Overflow来说,这个范围太广了。简而言之,您只需像其他任何形式一样在表单中为其渲染字段。您只需要注意输入的命名,因为您需要维护对象层次结构。例如,如果您正在编辑
Device
,则将为deviceType
输入类似:<input type="text" name="deviceType.Name" />
但是,只要使用
*For
样式帮助器,大多数情况下效果就会很好。删除中
由于EF的默认设置是级联,因此这里实际上没有什么特别的要考虑的。如果出于某种原因您决定(或已在现有数据库中为您决定)不进行级联,则只需删除设备类型,然后再删除设备,即手动执行级联将执行的相同操作。
关于c# - 难以理解如何在ASP.net Core中处理数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43811282/