2017-05-05 51 views
1

我试图学习ASP.Net Core,而且我很难弄清楚如何在MVC'样式'(?)中移动数据。我所关注的微软网站上的ASP.NET Core教程并不涉及模型之间的任何关系。 (对他们来说,似乎是一个愚蠢的疏忽?)也许我的Google-Fu关闭了,所以如果这是明显的,或者任何人有一些阅读材料,我可以看看ASPNETCore,我会很感激。理解如何在ASP.net中处理数据时遇到问题核心

我有两个模型。一个叫设备,另一个叫做设备类型。 在我的设备模型中,我有一个对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。我也不明白如何在处理我的视图时参考相关的设备类型。

GET创建 *如何让我的DeviceTypes的选择列表,以便用户可以创建一个设备,然后选择它是什么类型的设备? *我对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代码的asp.net核心应用程序”外,我还可以看到其他一些资源,这将解释如何在视图/控制器内部的模型中引用关系,这很好。

谢谢

回答

3

首先,我假设正在这里使用实体框架,因为这是迄今为止最常用的设置。

获取deviceType

随着EF,关系可以懒洋洋地,兴致勃勃,还是明确地加载。延迟加载是自动驾驶仪的方法:当你需要时,数据只是神奇的。但是,为了启用延迟加载,该属性必须为virtual。这是因为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这样的属性。你有两个选择:

  1. 属性添加到Device为外键,而不是依赖隐一个EF将创建:

    public int deviceTypeId { get; set; } 
    
  2. 与像上面的属性创建一个视图模型。在发布后,您会将视图模型中的值映射到您的实体上,当涉及到deviceTypeId时,您将使用它从数据库中提取适当的设备类型,然后使用该设置在您的实体上设置deviceType

接下来,你需要一个IEnumerable . Don't bother creating an actual SelectList`实例。剃刀可以照顾到这一点,而当你让剃刀处理它时,事情通常会更顺利。创建是相当直接:

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

  1. @Html.DisplayFor(m => m.Name)
  2. @Model.Name

编辑deviceType

这一个对堆栈溢出有点过于宽泛。简而言之,您只需在窗体中为其呈现字段,就像其他任何内容一样。您只需要注意输入的命名,因为您需要维护对象层次结构。例如,如果您正在编辑一个Device,你必须输入为deviceType,如:

<input type="text" name="deviceType.Name" /> 

但是,只要您使用*For风格佣工,本身工作了大部分。

删除

有算不上什么特别的考虑这里,作为EF的默认值是级联。如果由于某种原因,你决定(或者已经决定在现有的数据库中),以便不级联,那么在删除设备之前,你只需要删除设备类型即手动做同样的事情级联会。

+0

EF Core尚未对延迟加载进行加载。 https://docs.microsoft.com/en-us/ef/core/querying/related-data – Alexan

+0

@Alex:是的,我忘了这一点。或者,也许我只是觉得他们已经排序了将近两年;)。没什么大不了。老实说,我还没有看到很多好的理由来延迟加载,反正。一般来说,你只需要加载你需要的一切。 –

+0

即使EF支持它,也不要在网络应用程序中使用延迟加载,只要您可以提供帮助。这是为什么:http://ardalis.com/avoid-lazy-loading-entities-in-asp-net-applications – ssmith

1

获得设备列表时,假设这是使用实体框架包括设备类型,使用包括像_context.Device.Include(d => d.DeviceType).ToListAsync()。这将会......包括您指定的关联实体。实体框架还有很多,所以我建议在处理模型和上下文时查找更多信息。

至于你可以选择的类型列表,你首先需要分别获得可用设备类型的列表,然后将它传递给视图(在viewbag中,或者你选择),然后......我还没有和MVC核心的工作很多,但我怀疑这是相当类似老版本,但无论如何像MVC6 Dropdownlist of Countries

0

首先你需要包括外键在您的设备型号:

public int DeviceTypeID {get; set;} 

然后你应该包括这个设备类型属性如何answered here

_context.Device.Include(d => d.DeviceType).ToListAsync()