数据存储到 ASP.NET Core 5 MVC 中的关联表
Posted
技术标签:
【中文标题】数据存储到 ASP.NET Core 5 MVC 中的关联表【英文标题】:Data storing to the associated table in ASP.NET Core 5 MVC 【发布时间】:2021-07-24 07:51:36 【问题描述】:我有三个表“电影”、“流派”,它与表“电影流派”相关联。我要做的是将 Movie 表的值与 Genre 表结合起来,并使用第三个关联表 MovieGenre 显示 Genre 表中的 Name 值和 Movie 表值。
public partial class Movie
public int MovieId get; set;
[Required]
public string Title get; set;
public string Description get; set;
public string Storyline get; set;
public int? Year get; set;
[DataType(DataType.Date)]
[Validators(ErrorMessage = "Date must be after or equal to current date")]
[Display(Name = "Release Date")]
public DateTime? ReleaseDate get; set;
public int? Runtime get; set;
[Display(Name = "Movie Type")]
[Column(TypeName = "nvarchar(20)")]
public MovieType MovieType get; set;
public ICollection<Genre> Genres get; set;
public class Genre
[Key]
public int GenreId get; set;
[Display(Name="Genre name")]
public string Name get; set;
public ICollection<Movie> Movies get; set;
public class MovieGenre
public int MovieGenreId get; set;
public int MovieId get; set;
public Movie Movie get; set;
public int GenreId get; set;
public Genre Genre get; set;
这是这个的上下文页面
public partial class MovieContext : DbContext
public MovieContext(DbContextOptions<MovieContext> options)
: base(options)
public virtual DbSet<Movie> Movies get; set;
public virtual DbSet<Genre> Genre get; set;
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
modelBuilder.Entity<MovieGenre>().HasKey(mg => new mg.MovieId, mg.GenreId );
modelBuilder.Entity<Movie>()
.HasMany(p => p.Genres)
.WithMany(p => p.Movies)
.UsingEntity(j => j.ToTable("MovieGenre"));
OnModelCreatingPartial(modelBuilder);
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
我使用了数据库优先的方法。我已经创建了所有其他部分,当我从数据库向表中输入值时它工作正常。但我想要实现的是在创建新电影时将外键值“MovieId”和“GenreId”存储到“MovieGenre”表中。
这是创建动作方法中的代码。如何通过此代码将“MovieId”和“GenreId”存储到“MovieGenre”表中?
public async Task<IActionResult> Create([Bind("Title,Description,Storyline,Year,ReleaseDate,Runtime,MovieType")] Movie movies)
if (ModelState.IsValid)
_context.Add(movies);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
ViewBag.GenreId = new MultiSelectList(_context.Genre.ToList(), "GenreId", "Name");
return View(movies);
下面是创建 Action 视图的代码,这里我使用了 Genre 的复选框,我也想从这里以某种方式将 GenreId 输入到关联表中。
<div class="row">
<div class="col-md-4 center">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Storyline" class="control-label"></label>
<input asp-for="Storyline" class="form-control" />
<span asp-validation-for="Storyline" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Year" class="control-label"></label>
<input asp-for="Year" class="form-control" />
<span asp-validation-for="Year" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Runtime" class="control-label"></label>
<input asp-for="Runtime" class="form-control" />
<span asp-validation-for="Runtime" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MovieType" class="control-label"></label>
<select asp-for="MovieType" class="form-control" asp-items="html.GetEnumSelectList<MovieType>()"></select>
<span asp-validation-for="MovieType" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">Movie Genre</label>
<div class="col-md-10">
<div class="checkbox">
@foreach (var item in (MultiSelectList)ViewBag.GenreId)
<input type="checkbox" value="@item.Value" id="GenreId" name="GenreId" />@item.Text
</div>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
<a class="btn btn-primary" asp-action="Index">Back to List</a>
</div>
</form>
</div>
</div>
@section Scripts
@await Html.RenderPartialAsync("_ValidationScriptsPartial");
【问题讨论】:
【参考方案1】:我已经找到了正确的代码。如果有人需要这里的解决方案,请在我的 GitHub 存储库中找到完整的代码。
https://github.com/Iam-Goku/ProjectMovie.git
【讨论】:
【参考方案2】:但我想要实现的是在创建新电影时将外键值“MovieId”和“GenreId”存储到“MovieGenre”表中。
您实际上并不需要MovieId
,因为它是在调用SaveChangesAsync
时自动生成的,因此只有在调用之后才可用。
但是你有明确的连接实体MovieGenre
和 navigation 和明确的 FK 属性,所以你可以利用导航属性来指定新的Movie
并让EF Core 为您处理实际的 FK。对于其他 FK,您只需分配 existing Genre
键 (Id)。
在这种情况下,有两种方法可以添加新的MovieGenre
记录。两者都需要创建MovieGenre
实例并填写导航和FK 属性:
var movieGenre = new MovieGenre
Movie = movies,
GenreId = genreId // ?? - see below
;
只是不确定GenreId
来自哪里
Create([Bind("MovieId,Title,Description,Storyline,Year,ReleaseDate,Runtime,MovieType, GenreId")] Movie movies
由于Movie
类没有GenreId
属性,因此您必须弄清楚这一点(最终重新访问用于与控制器通信的 DTO/ViewModel)。
一旦你有了它,你可以将它添加到 Movie.MovieGenre
集合中:
movies.MovieGenre = new List<MovieGenre> movieGenre ;
_context.Add(movies);
或直接将其添加到数据库上下文(集):
_context.Add(movies);
_context.Add(movieGenre);
对于这种特殊情况,显式连接实体有很大帮助。如果您改为使用 EF Core 5.0+ 隐式连接实体,则实现该操作将需要不同的方法。
【讨论】:
很遗憾,asp net 不是我的领域(零经验),我只能回答与 EF Core 相关的问题。以上是关于数据存储到 ASP.NET Core 5 MVC 中的关联表的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ASP.NET Core 5 MVC (.NET 5) 中获取记录的用户数据?
使用存储过程时出现 ASP.Net Core 3.1 MVC 错误
ASP.net core MVC Framework 5 Formdata在附加图像时类型不正确
从 ASP.NET MVC 5 移植到 dotnet core 2:可能替代 System.Web.Mvc.HttpStatusCodeResult [重复]