c# - 试图从数据库表中读取,但输出不正确
问题描述
这是我的代码:
曲目.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>
曲目.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
,whileAlbumId
是表的外键Tracks
。
.Where(a => a.AlbumId == Tracks.AlbumId)
也许我需要像and这样的子句.Where(a => a.ArtistId == Album.ArtistId)
?我试图写这样的东西,但我一定是做错了,因为它完全阻止了曲目的显示。请问有什么帮助吗?TIA
编辑:我注意到虽然我的专辑标题是从Album
表中加入的,但我的艺术家姓名不是,即使方法本质上是相同的。我突然想到,虽然Album
表直接连接到Track
表(通过AlbumId
外键),但Artist
表不是。它只是通过Album
table` 间接与“Track”表相关。
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)无关,则必须分开。以下是我修改的代码。
上下文.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);
}
实体.艺术家
public class Artist
{
public int ArtistId { get; set; }
public string Name { get; set; }
public ICollection<Album> Albums { get; set; }
}
实体.流派
public class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public ICollection<Track> Tracks { get; set; }
}
Entity.Media_type
public class Media_type
{
public int MediaTypeId { get; set; }
public string Name { get; set; }
public ICollection<Track> Tracks { get; set; }
}
实体.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>
参考: 实体框架核心关系
推荐阅读
- asterisk - 如何在星号上获取 sip 调试中返回的数据?
- c - 数组元素超出C中的索引
- javascript - 将所选图像 url 应用于隐藏表单输入类型
- nginx - 请求到达后立即记录到 nginx
- math - if(n%2==0) 或 if(n&1==0) 哪个更快找到偶数?
- python - Python假设:确保输入列表具有相同的长度
- php - 本地主机不同于 127.0.0.1
- r - 如何为 sankeyNetwork() 定义节点和链接数据框
- java - 我需要为我的应用程序获取 API 密钥,为此,我需要我的证书的 MD5 签名
- c++ - QT C++ 如何调用 lambda one?