2015-02-08 67 views
2

我的目標是使用EF7和MVC6 [BETA2]列出每個書架的書架數量和書架數量。EF7的實體關係MVC6

使用正確的表關係正確創建數據庫模式。我可以成功地將書架和書籍添加到數據庫中,包括外鍵關係(請參閱下面的代碼)。

當我測試應該在每個書架上顯示書數的索引頁時,我沒有收到書計數數據並且沒有錯誤。在架子實體屬性書籍仍然未填充Book實體因此計數爲空(請參閱下面的代碼)。

在EF7有什麼地方我需要編寫代碼來填充Shelf.Books或者這應該在EF7中自動發生?

BookShelf.cs

namespace MyApp.Models 
{ 
    public class Shelf 
    { 
     public int ShelfId { get; set; } 
     public string Name { get; set; } 
     public virtual List<Books> Books { get; set; } 
    } 

    public class Book 
    { 
     public int BookId { get; set; } 
     public string Name { get; set; } 
     public int ShelfId { get; set; } 
     public Shelf Shelf{ get; set; } 
    } 
} 

ApplicationDbContext.cs

namespace MyApp 
{ 
    public class ApplicationDBContext 
    { 
     public DbSet<Shelf> Shelf { get; set; } 
     public DbSet<Book> Book { get; set; } 
    } 

    protected override void OnModelCreating(ModelBuilder builder) 
    { 
     builder.Entity<Shelf>().Key(s => s.ShelfId); 
     builder.Entity<Book>().Key(b => b.BookId); 

     builder.Entity<Shelf>()     
      .OneToMany(s => s.Book) 
      .ForeignKey(k => k.ShelfId); 

     base.OnModelCreating(builder); 
    } 
} 

ShelfController.cs

namespace MyApp 
{ 
    private ApplicationDBContext db; 

    public BuildingsController(ApplicationDBContext context) 
    { 
     db = context; 
    } 

    // GET: Shelves 
    public async Task<IActionResult> Index() 
    { 
     return View(await db.Shelves.ToListAsync()); 
    } 
} 

Index.cshtml

... 
@foreach (var item in Model) { 
    <tr> 
     <td> 
      @Html.DisplayFor(modelItem => item.Name) 
     </td> 
     <td> 
      @Html.DisplayFor(modelItem => item.Books.Count) 
     </td> 
    </tr> 
} 
.... 
+0

可能是因爲'db.Shelves.ToListAysnc()'創建了一個在控制器範圍之外使用的Shelves列表,所以'Books'永遠不會被填充。其次,除非事情自6.1起改變,你的'書籍'屬性應該是'ICollection '。最後,您應該創建一個View模型,它實際上代表視圖需要的數據,而不是依賴視圖中的方法來執行邏輯(如計數,這很可能是爲什麼它不起作用)。 – 2015-02-08 21:08:38

+0

謝謝@ErikPhilips! – Will 2015-02-08 21:13:38

+0

'ICollection '已在EF7中更改爲'列表'。從你的評論我不確定如果你說它不填充,因爲我沒有使用視圖模型或因爲'db.Shelves.ToListAsync()'超出了範圍。你會如何改變它? – Will 2015-02-08 21:19:19

回答

0

看看ICollection Vs List in Entity Framework。我有一種感覺,EF7使用List<>的小例子是不正確的(很難想象,使用EF7的最佳做法是從ICollection<>更改爲List<>,但將具體集合類型公開爲屬性通常是非常糟糕的做法。)

根據您的意見我會改變:

創建視圖模型

public class IndexViewModel 
{ 
    public IEnumerable<ShelveModel> Shelves { get; set; } 
} 

public class ShelveModel 
{ 
    public string Name { get; set; } 
    public int BookCount { get ; set; } 
} 

更新邏輯

// GET: Shelves 
public async Task<IActionResult> Index() 
{ 
    var model = new IndexViewModel(); 
    model.Shelves = db.Shelves 
     .Select(s => new 
     { 
      Name = s.Name, 
      BookCount = s.Books.Count() 
     }) 
     .ToListAsync() 
     .Select(s => new ShelveModel() 
     { 
      Name = s.Name, 
      BookCount = s.Books.Count() 
     }) 
     .ToList(); 

    return View(model); 
} 
+0

Index()給我一個時髦的錯誤:處理請求時發生未處理的異常。 InvalidOperationException:當從'VisitMethodCallExpression'中調用時,'Expression'類型的表達式只能用類型'Expression'的其他非空表達式替換。 Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitAndConvert [T](T expression,String methodName) '有什麼想法? – Will 2015-02-08 22:57:49

+0

這個問題似乎與'shelfIndexViewModel.ShelfModels = await'中的'await'有關,因爲它可能是主題。 – Will 2015-02-08 23:06:45

+0

該代碼對'async'函數內部缺少'await'不滿意。 – Will 2015-02-09 14:39:26

0

我發現的是,EF沒有用相關的子對象填充父對象。例如,myShelf.Books將在控制器動作函數中填充之前爲空。