2014-09-01 49 views
2

我有一個名爲'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 ,所以任何幫助感激地收到。

謝謝!

回答

4

今後,像這樣的問題,它,如果你發佈你的實際實體類是最好的。但是,根據您的表格,看起來您在JobTitleOffice之間存在多對多關係。您的困難很可能與如何訪問特定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所有查詢來獲取職稱。然後,您可以使用任何此類信息做任何您想要的,而無需擔心發出多個附加查詢。

+0

謝謝克里斯,非常有幫助的解釋。 – Martin 2014-09-02 08:05:55

0

您可以使用SelectManySelect將結果投影到JobTitleNameOfficeName的集合中。

<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; } 
} 

更多

相關問題