2012-07-27 45 views
1

我有幾個類,爲簡潔起見,我將縮短這些類。以下列出了與此問題相關的相關屬性/字段。如何使用複雜的表結構在MVC中加載相關數據

public class AcademicYear 
{ 
    [Key] 
    public int AcademicYearId { get; set; } 
} 

public class Division 
{ 
    public Division() 
    { 
     this.CareerFields = new HashSet<CareerField>(); 
    } 

    [Key] 
    public int DivisionId  { get; set; } 

    // Foreign Keys 
    public int AcademicYearId { get; set; } 

    // Navigation Properites 
    public virtual AcademicYear AcademicYear { get; set; } 

    public virtual ICollection<CareerField> CareerFields { get; set; } 
} 

public class CareerField 
{ 
    public CareerField() 
    { 
     this.Clusters = new HashSet<Cluster>(); 
    } 

    [Key] 
    public int CareerFieldId { get; set; } 

    // Foreign Keys 
    public int AcademicYearId { get; set; } 
    public int DivisionId  { get; set; } 


    // Navigation Properties 
    public virtual AcademicYear AcademicYear { get; set; } 
    public virtual Division  Division  { get; set; } 

    public virtual ICollection<Cluster> Clusters { get; set; } 
} 

public class Cluster 
{ 
    public Cluster() 
    { 
     this.CareerFields = new HashSet<CareerField>(); 
    } 

    [Key] 
    public int ClusterId { get; set; } 
    { 
     // Foreign Keys 
     public int AcademicYearId { get; set; } 

     // Navigation Properties 
     public virtual AcademicYear AcademicYear { get; set; } 

     public virtual ICollection<CareerField> CareerFields { get; set; } 
    } 
} 

public class Pathway 
{ 
    public Pathway() 
    { 
     this.CareerMajors = new HashSet<CareerMajor>(); 
    } 

    [Key] 
    public int PathwayId  { get; set; } 

    // Foreign Keys 
    public int AcademicYearId { get; set; } 
    public int ClusterId  { get; set; } 

    // Navigation Properties 
    public virtual AcademicYear AcademicYear { get; set; } 
    public virtual Cluster  Cluster  { get; set; } 

    public virtual ICollection<CareerMajor> CareerMajors { get; set; } 
} 

public class CareerMajor 
{ 
    public CareerMajor() 
    { 
     this.Courses  = new HashSet<Course>(); 
    } 

    [Key] 
    public int CareerMajorId  { get; set; } 
    public string FirstYearOffered { get; set; } 

    // Foreign Keys 
    public int AcademicYearId { get; set; } 
    public int PathwayId   { get; set; } 

    // Navigation Properties 

    [HiddenInput(DisplayValue = false)] 
    public virtual AcademicYear  AcademicYear  { get; set; } 
    public virtual Pathway   Pathway   { get; set; } 

    public virtual ICollection<Course>   Courses  { get; set; } 

} 

public class Course 
{ 
    public Course() 
    { 
     this.CareerMajors = new HashSet<CareerMajor>(); 
    } 

    [Key] 
    public int CourseId  { get; set; } 

    // Foreign Keys 
    public int AcademicYearId { get; set; } 
    public int? InstructorId { get; set; } 

    // Navigation Properties 
    public virtual ICollection<CareerMajor> CareerMajors { get; set; } 

    public virtual AcademicYear AcademicYear { get; set; } 
} 

我也有一個ViewModel類加載這一切對我的控制器

public class CMSIndex 
{ 
    public IEnumerable<Division> Divisions { get; set; } 
    public IEnumerable<CareerField> CareerFields { get; set; } 
    public IEnumerable<Cluster> Clusters { get; set; } 
    public IEnumerable<Pathway> Pathways { get; set; } 
    public IEnumerable<CareerMajor> CareerMajors { get; set; } 
    public IEnumerable<Course> Courses { get; set; } 
} 

我有一個剃鬚刀CSHTML頁面(自動CRUD定義的索引頁),在那裏我開始與我司與以能加載相關的CareerFields。但是,當我嘗試加載羣集時,收到錯誤消息

'/'應用程序中的服務器錯誤。 值不能爲空。 參數名稱:source 描述:執行當前Web請求期間發生未處理的異常。請查看堆棧跟蹤以獲取有關該錯誤的更多信息以及源代碼的位置。

異常詳細信息:System.ArgumentNullException:值不能爲空。 參數名:源

這裏是從控制器我的索引方法(注意註釋掉線是我曾嘗試爲好)

public ViewResult Index(Int32? divisionID, Int32? careerFieldID, Int32? clusterID, Int32? pathwayID, Int32? careerMajorID, Int32? courseID) 
    { 
     var viewModel = new CMSIndex(); 

     viewModel.Divisions = db.Divisions 
      .Include(d => d.AcademicYear) 
      .Include(d => d.CareerFields)// 
      .Include(d => d.CareerFields.Select(cf => cf.Clusters)) 
      //.Select(c => c.Clusters.Select(cl => cl.Pathways.Select(p => p.CareerMajors.Select(cm => cm.Courses))))) 
      .OrderBy(d => d.DivisionName); 

     if (divisionID != null) 
     { 
      ViewBag.DivisionID = divisionID.Value; 
      viewModel.CareerFields = viewModel.Divisions.Where(d => d.DivisionId == divisionID.Value).Single().CareerFields; 
     } 

     if (careerFieldID != null) 
     { 
      ViewBag.careerFieldID = careerFieldID.Value; 
      //viewModel.Clusters = viewModel.CareerFields.Where(cf => cf.CareerFieldId == careerFieldID.Value).Single().Clusters; 
      //viewModel.Clusters = viewModel.CareerFields.SelectMany(cf => cf.Clusters); 
      viewModel.Clusters = viewModel.CareerFields.Where(cf => cf.CareerFieldId == careerFieldID.Value).Single().Clusters; 
     } 

     return View(viewModel); 
    } 

我下面的加載相關數據Contoso的教程。我似乎能夠加載1:m的關係,但我不確定如何使用m:m(例如CareerFields和Clusters)執行此操作。

而且,我確實有一個初始化程序,它已經加載了要拉的數據,並且正在傳遞一個ID(例如,careerFieldID)。

在異常被拋出就行了:

viewModel.Clusters = viewModel.CareerFields.Where(cf => cf.CareerFieldId == careerFieldID.Value).Single().Clusters; 

而且每個評論的變化。

任何幫助將不勝感激。

回答

1

不是說這是問題,而是你檢查過的值是否爲空?在線

viewModel.Clusters = viewModel.CareerFields 
    .Where(cf => cf.CareerFieldId == careerFieldID.Value).Single().Clusters; 

是否有可能viewModel.CareerFields爲空?

正如一些旁註:

  • 有了您的null檢查,當你有nullables這是更好地使用例如他們的HasValue方法

    if (divisionID.HasValue) 
    { 
        ... 
    } 
    
  • 採用Single()可以是一個有點脾氣,如果沒有元素存在或無法拋出異常,如果超過一個存在。 First()可用於處理多個(但是如果沒有匹配則拋出),SingleOrDefault()將處理零個或一個結果,並且FirstOrDefault()將處理大多數事情。

  • 您可以通過將lambda放入單個例如表達式來保存表達式。

    viewModel.CareerFields = viewModel.Divisions 
        .Single(d => d.DivisionId == divisionID.Value).CareerFields; 
    

編輯:我想你遇到的問題是一樣的This Answer你可以嘗試改變你的類的集合,因此都在get初始化時爲空。 E.g爲

public class Division 
{ 
    [Key] 
    public int DivisionId  { get; set; } 

    // Foreign Keys 
    public int AcademicYearId { get; set; } 

    // Navigation Properites 
    public virtual AcademicYear AcademicYear { get; set; } 

    private ICollection<CareerField> careerFields; 
    public virtual ICollection<CareerField> CareerFields { 
     get { return careerFields ?? (careerFields = new HashSet<CareerField>()); } 
     set { careerFields = value; } 
    } 
} 

這實際上是我的首選方法,無論如何,這會帶來它自己的問題,你的代碼的事實,CareerFields爲空意味着對於給定的部門,有沒有相關的CareerFields。這意味着當您的Single()調用被觸發時,它將拋出異常The source contains no elements,因爲CareerFields將包含一個空的哈希集。這可以通過更改SingleOrDefault()來解決。

+0

感謝您的回覆。是的,我很確定它是空的(集羣,而不是careerField.ID ...我證實這不是空)。我知道在我的數據庫中有我正在尋找的值,我只是不確定是否正確設置查詢以查詢m:m關係。 is viewModel.Clusters = viewModel.CareerFields 。Where(cf => cf.CareerFieldId == careerFieldID.Value).Single()。Clusters;正確?另外,我是否正確加載相關數據? – Erik 2012-07-28 01:47:40

+0

@Erik你的加載看起來不錯。我相信這不是集羣,而是分工的職業領域。我編輯了我的問題,但後來發現你說'我知道我的數據庫中有什麼價值觀'實體框架似乎並不瞭解與搜索部門相關的CareerFields。他們是否肯定在數據庫中,他們之間是否存在多對多的關聯(在鏈接表中?是實體框架意識到它?)。 – Manatherin 2012-07-28 06:00:51

+0

各部門正在加載。當我選擇職業領域來加載集羣的時候是失敗的時候。在viewModel.Clusters = viewModel.CareerFields.Where(cf => cf.CareerFieldId == careerFieldID.Value).Single()。集羣中引發異常。 - 我嘗試過SingleOrDefault,但仍然得到空錯誤。我可以告訴問題在哪裏。 ViewModel的CareerField.Clusters沒有被加載,我只是不知道如何加載它們。我是否需要在視圖模型或控制器中加載它? – Erik 2012-07-31 15:53:56