如何在MVC中显示来自导航属性集合的值索引页
我有一个名为'JobTitle'的EF实体类型,它具有一个名为'Offices'的导航属性(这是另一个名为'Office'的实体类型的集合)。如何在MVC中显示来自导航属性集合的值索引页
我想在我的索引视图中显示JobTitle名称和相关Office名称的列表。 观脚手架生成默认的情况如下:
@model IEnumerable<Example.Models.JobTitle>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.JobTitleName)
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.JobTitleName)
</td>
</tr>
}
</table>
我的控制器代码(默认)看起来像:
// GET: /JobTitle/
public ActionResult Index()
{
return View(db.JobTitles.ToList());
}
这将让我产生一切简单的属性属于' JobTitle'(如'JobTitleName')。不过,我无法弄清楚如何从“办公室”集合(导航属性)中检索相应的“办公室”信息到我的视图中。
因此,我希望最终显示两列'JobTitle'和'Office'。
(在我的数据库,这些实体是由三个表表示:JOBTITLE(JobTitleID,JobTitleName),办公室(OfficeID,OfficeName)和JobTitleOffice(JobTitleID,OfficeID))
我完全新的MVC和Entity Framework ,所以任何帮助感激地收到。
谢谢!
今后,像这样的问题,它,如果你发布你的实际实体类是最好的。但是,根据您的表格,看起来您在JobTitle
和Office
之间存在多对多关系。您的困难很可能与如何访问特定JobTitle
实例的OfficeName
属性有关,并且存在的问题不仅仅是一个OfficeName
,而是很多。您需要遍历Office
s的列表。
<td>
@Html.DisplayFor(modelItem => item.JobTitleName)
@foreach (var office in item.Offices)
{
@Html.DisplayFor(m => office.OfficeName)
}
</td>
如果你想有一个稍微好一点的显示器,您可能希望打开办公室的名称为逗号分隔的列表(例如:,Office Name 1, Office Name 2, ...
),它可以通过执行以下操作,而不是使用foreach来实现:
<td>
@Html.DisplayFor(modelItem => item.JobTitleName)
@string.Join(", ", item.Offices.Select(m => m.OfficeName))
</td>
或者,如果你只关心呈现一个办公室的名称,你可以使用FirstOrDefault
拉出一个办公室:
<td>
@Html.DisplayFor(modelItem => item.JobTitleName)
@{
var office = item.Offices.FirstOrDefault();
if (office != null)
{
@Html.DisplayFor(m => office.OfficeName);
}
}
</td>
您应该经常检查null
首先,以防万一实际上没有相关的办公室。
基本上,您选择哪种方法取决于您的应用程序的要求。另外,请注意实体框架延迟加载相关项目。这里并没有那么糟糕,因为第一次尝试访问Offices
时,将发出一个新的查询来获取相关的办公室。因为你并没有试图访问Office
以外的任何相关属性,所以一个额外的查询不会有太大的影响。但考虑到以下几点:
public class Office
{
...
public virtual Address Address { get; set; }
}
如果你试图做这样的事情:
@foreach (var office in item.Offices)
{
@office.OfficeName
<address>
@office.Address.Street
...
</address>
}
你最终用什么所谓的N + 1个查询,在那里你有一个查询来获取集合(Offices
)然后一个查询取Address
为每个办公室(导致N
查询,其中N
是办事处总数)。在这种情况下,你最好是急于加载。例如,
return View(db.JobTitles.Include("Offices.Address").ToList());
,会导致实体框架做了一个连接以包括每个Office
实例都Offices
每个Address
所有查询来获取职称。然后,您可以使用任何此类信息做任何您想要的,而无需担心发出多个附加查询。
您可以使用SelectMany
和Select
将结果投影到JobTitleName
和OfficeName
的集合中。
<table>
<tr>
<th>@Html.DisplayNameFor(model => model.JobTitleName)</th>
<th>Office</th>
</tr>
@{
var items = Model
.SelectMany(j => j.Offices
.Select(o => new { j.JobTitleName, o.OfficeName }));
}
@foreach (var item in items) {
<tr>
<td>@Html.DisplayFor(modelItem => item.JobTitleName)</td>
<td>@Html.DisplayFor(modelItem => item.OfficeName)</td>
</tr>
}
</table>
PS
的Offices
集合将自动被加载(执行的foreach时),如果你对导航性能virtual
关键字,并使用默认配置(代理+延迟加载)。这被称为延迟加载。
public class JobTitle
{
// other properties
public string JobTitleName { get; set; }
public virtual ICollection<Office> Offices { get; set; }
}
public class Office
{
// other properties
public string OfficeName { get; set; }
public virtual ICollection<JobTitle> JobTitles { get; set; }
}
更多
谢谢克里斯,非常有帮助的解释。 – Martin 2014-09-02 08:05:55