尝试从数据库 table 读取,但输出不正确
Trying to read from database table, but output is incorrect
这是我的代码:
tracks.cshtml
@page
@using Project.Models
@model Project.Pages.TracksModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Tracks</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Artist name</th>
<th>Album name</th>
<th>Track ID</th>
<th>Track name</th>
</tr>
</thead>
<tbody>
@foreach (Track track in Model.Tracks)
{
<tr>
<td>@Html.DisplayFor(modelArtists => track.Artist.Name)</td>
<td>@Html.DisplayFor(modelAlbums => track.Album.Title)</td>
<td>@track.TrackId</td>
<td>@track.Name</td>
<td><a asp-page="/Tracks/Details" asp-route-id="@track.TrackId">Details</a></td>
<td><a asp-page="/Tracks/Edit" asp-route-id="@track.TrackId">Edit</a></td>
<td><a asp-page="/Tracks/Delete" asp-route-id="@track.TrackId">Delete</a></td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<p>Enter a name & TrackID (over 3510) for a new track: </p>
<form method="POST">
<div><input asp-for="Track.Name" /></div>
<div><input asp-for="Track.TrackId" /></div>
<input type="submit" />
</form>
</div>
<div>
<a asp-page="/Index">Home</a>
</div>
tracks.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Project.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Project.Pages
{
public class TracksModel : PageModel
{
private Chinook db;
public TracksModel(Chinook injectedContext)
{
db = injectedContext;
}
public IEnumerable<Track> Tracks { get; set; }
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks.Include(a => a.Album)
.Include(a => a.Artist);
}
[BindProperty]
public Track Track { get; set; }
public IActionResult OnPost()
{
if (ModelState.IsValid)
{
db.Tracks.Add(Track);
db.SaveChanges();
return RedirectToPage("/tracks");
}
return Page();
}
public IActionResult DeleteTrack(int TrackId)
{
var track = db.Tracks.Find(TrackId);
if (track == null) return Page();
db.Tracks.Remove(track); db.SaveChanges(); return RedirectToPage("/tracks");
}
}
}
出现问题,页面似乎多次重复艺术家姓名,以至于所有显示的艺术家姓名都以字母 A 开头。我应该说我设置数据库的方式向上,ArtistId
是Album
table的外键,而AlbumId
是Tracks
table.[=31的外键=]
也许我需要 .Where(a => a.AlbumId == Tracks.AlbumId)
和 .Where(a => a.ArtistId == Album.ArtistId)
这样的子句?我试图写类似的东西,但我一定是做错了,因为它只是阻止了曲目完全显示。有什么帮助吗? TIA
编辑:我注意到虽然我的专辑标题是从 Album
table 加入的,但我的艺术家姓名不是,即使方法本质上是一样的。在我看来,虽然 Album
table 直接连接到 Track
table(通过 AlbumId
外键),但 Artist
table 不是。它仅通过 Album
table` 与 'Track' table 间接相关。
Artist
----Album
----Track
Edit2:有人告诉我在这种情况下不需要 Where
,我应该使用“ThenInclude”,所以我目前有
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks.Include(a => a.Album).ThenInclude(b => b.Artist).ToList();
}
它仍然导致完全相同的错误。
重点在Context.Chinook.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(mtype => mtype.Artist)
.WithMany(trk => trk.Tracks)
.HasForeignKey(mtype => mtype.AlbumId)
.HasForeignKey(mtype => mtype.GenreId)
.HasForeignKey(mtype => mtype.MediaTypeId)
.OnDelete(DeleteBehavior.NoAction);
}
HasForeignKey 链如果与上述关系(1 到 n,n 到 1,1 到 1)无关,则必须分开。
以下是我修改过的代码
Context.Chinook.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Album>()
.ToTable("albums")
.HasOne(al => al.Artist)
.WithMany(ar => ar.Albums)
.HasForeignKey(al => al.ArtistId);
modelBuilder.Entity<Artist>().ToTable("artists");
modelBuilder.Entity<Media_type>()
.ToTable("media_types")
.HasKey(c => c.MediaTypeId);
modelBuilder.Entity<Genre>().ToTable("genres");
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(trk => trk.Album)
.WithMany(trk => trk.Tracks)
.HasForeignKey(trk => trk.AlbumId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(trk => trk.Genre)
.WithMany(trk => trk.Tracks)
.HasForeignKey(trk => trk.GenreId);
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(trk => trk.Media_type)
.WithMany(trk => trk.Tracks)
.HasForeignKey(mtype => mtype.MediaTypeId);
}
Entities.Artist
public class Artist
{
public int ArtistId { get; set; }
public string Name { get; set; }
public ICollection<Album> Albums { get; set; }
}
Entities.Genre
public class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public ICollection<Track> Tracks { get; set; }
}
Entities.Media_type
public class Media_type
{
public int MediaTypeId { get; set; }
public string Name { get; set; }
public ICollection<Track> Tracks { get; set; }
}
Entities.Track
public class Track
{
public int TrackId { get; set; }
public string Name { get; set; }
public int? AlbumId { get; set; }
public int? MediaTypeId { get; set; }
public int? GenreId { get; set; }
public string Composer { get; set; }
public int? Milliseconds { get; set; }
public int? Bytes { get; set; }
public int? UnitPrice { get; set; }
public Album Album { get; set; }
public Genre Genre { get; set; }
public Media_type Media_type { get; set;}
}
WebApp.tracks.cshtml.cs
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks
.Include(a => a.Album)
.ThenInclude(a => a.Artist);
}
WebApp.tracks.cshtml
<tbody>
@foreach (Track track in Model.Tracks)
{
<tr>
<td>@Html.DisplayFor(modelArtists => track.Album.Artist.Name)</td>
<td>@Html.DisplayFor(modelAlbums => track.Album.Title)</td>
<td>@track.TrackId</td>
<td>@track.Name</td>
<td><a asp-page="/Tracks/Details" asp-route-id="@track.TrackId">Details</a></td>
<td><a asp-page="/Tracks/Edit" asp-route-id="@track.TrackId">Edit</a></td>
<td><a asp-page="/Tracks/Delete" asp-route-id="@track.TrackId">Delete</a></td>
</tr>
}
</tbody>
这是我的代码:
tracks.cshtml
@page
@using Project.Models
@model Project.Pages.TracksModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Tracks</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Artist name</th>
<th>Album name</th>
<th>Track ID</th>
<th>Track name</th>
</tr>
</thead>
<tbody>
@foreach (Track track in Model.Tracks)
{
<tr>
<td>@Html.DisplayFor(modelArtists => track.Artist.Name)</td>
<td>@Html.DisplayFor(modelAlbums => track.Album.Title)</td>
<td>@track.TrackId</td>
<td>@track.Name</td>
<td><a asp-page="/Tracks/Details" asp-route-id="@track.TrackId">Details</a></td>
<td><a asp-page="/Tracks/Edit" asp-route-id="@track.TrackId">Edit</a></td>
<td><a asp-page="/Tracks/Delete" asp-route-id="@track.TrackId">Delete</a></td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<p>Enter a name & TrackID (over 3510) for a new track: </p>
<form method="POST">
<div><input asp-for="Track.Name" /></div>
<div><input asp-for="Track.TrackId" /></div>
<input type="submit" />
</form>
</div>
<div>
<a asp-page="/Index">Home</a>
</div>
tracks.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Project.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Project.Pages
{
public class TracksModel : PageModel
{
private Chinook db;
public TracksModel(Chinook injectedContext)
{
db = injectedContext;
}
public IEnumerable<Track> Tracks { get; set; }
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks.Include(a => a.Album)
.Include(a => a.Artist);
}
[BindProperty]
public Track Track { get; set; }
public IActionResult OnPost()
{
if (ModelState.IsValid)
{
db.Tracks.Add(Track);
db.SaveChanges();
return RedirectToPage("/tracks");
}
return Page();
}
public IActionResult DeleteTrack(int TrackId)
{
var track = db.Tracks.Find(TrackId);
if (track == null) return Page();
db.Tracks.Remove(track); db.SaveChanges(); return RedirectToPage("/tracks");
}
}
}
出现问题,页面似乎多次重复艺术家姓名,以至于所有显示的艺术家姓名都以字母 A 开头。我应该说我设置数据库的方式向上,ArtistId
是Album
table的外键,而AlbumId
是Tracks
table.[=31的外键=]
也许我需要 .Where(a => a.AlbumId == Tracks.AlbumId)
和 .Where(a => a.ArtistId == Album.ArtistId)
这样的子句?我试图写类似的东西,但我一定是做错了,因为它只是阻止了曲目完全显示。有什么帮助吗? TIA
编辑:我注意到虽然我的专辑标题是从 Album
table 加入的,但我的艺术家姓名不是,即使方法本质上是一样的。在我看来,虽然 Album
table 直接连接到 Track
table(通过 AlbumId
外键),但 Artist
table 不是。它仅通过 Album
table` 与 'Track' table 间接相关。
Artist
----Album
----Track
Edit2:有人告诉我在这种情况下不需要 Where
,我应该使用“ThenInclude”,所以我目前有
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks.Include(a => a.Album).ThenInclude(b => b.Artist).ToList();
}
它仍然导致完全相同的错误。
重点在Context.Chinook.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(mtype => mtype.Artist)
.WithMany(trk => trk.Tracks)
.HasForeignKey(mtype => mtype.AlbumId)
.HasForeignKey(mtype => mtype.GenreId)
.HasForeignKey(mtype => mtype.MediaTypeId)
.OnDelete(DeleteBehavior.NoAction);
}
HasForeignKey 链如果与上述关系(1 到 n,n 到 1,1 到 1)无关,则必须分开。 以下是我修改过的代码
Context.Chinook.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Album>()
.ToTable("albums")
.HasOne(al => al.Artist)
.WithMany(ar => ar.Albums)
.HasForeignKey(al => al.ArtistId);
modelBuilder.Entity<Artist>().ToTable("artists");
modelBuilder.Entity<Media_type>()
.ToTable("media_types")
.HasKey(c => c.MediaTypeId);
modelBuilder.Entity<Genre>().ToTable("genres");
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(trk => trk.Album)
.WithMany(trk => trk.Tracks)
.HasForeignKey(trk => trk.AlbumId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(trk => trk.Genre)
.WithMany(trk => trk.Tracks)
.HasForeignKey(trk => trk.GenreId);
modelBuilder.Entity<Track>()
.ToTable("tracks")
.HasOne(trk => trk.Media_type)
.WithMany(trk => trk.Tracks)
.HasForeignKey(mtype => mtype.MediaTypeId);
}
Entities.Artist
public class Artist
{
public int ArtistId { get; set; }
public string Name { get; set; }
public ICollection<Album> Albums { get; set; }
}
Entities.Genre
public class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public ICollection<Track> Tracks { get; set; }
}
Entities.Media_type
public class Media_type
{
public int MediaTypeId { get; set; }
public string Name { get; set; }
public ICollection<Track> Tracks { get; set; }
}
Entities.Track
public class Track
{
public int TrackId { get; set; }
public string Name { get; set; }
public int? AlbumId { get; set; }
public int? MediaTypeId { get; set; }
public int? GenreId { get; set; }
public string Composer { get; set; }
public int? Milliseconds { get; set; }
public int? Bytes { get; set; }
public int? UnitPrice { get; set; }
public Album Album { get; set; }
public Genre Genre { get; set; }
public Media_type Media_type { get; set;}
}
WebApp.tracks.cshtml.cs
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks
.Include(a => a.Album)
.ThenInclude(a => a.Artist);
}
WebApp.tracks.cshtml
<tbody>
@foreach (Track track in Model.Tracks)
{
<tr>
<td>@Html.DisplayFor(modelArtists => track.Album.Artist.Name)</td>
<td>@Html.DisplayFor(modelAlbums => track.Album.Title)</td>
<td>@track.TrackId</td>
<td>@track.Name</td>
<td><a asp-page="/Tracks/Details" asp-route-id="@track.TrackId">Details</a></td>
<td><a asp-page="/Tracks/Edit" asp-route-id="@track.TrackId">Edit</a></td>
<td><a asp-page="/Tracks/Delete" asp-route-id="@track.TrackId">Delete</a></td>
</tr>
}
</tbody>