简体   繁体   中英

Data storing to the associated table in ASP.NET Core 5 MVC

I have three tables 'Movie', 'Genre' and it's associated table 'MovieGenre'. What I have to do is to combine the value of Movie table with Genre table and to display the Name value from Genre table with Movie table values, Using the third associated table MovieGenre.

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; }       
}

This is the Context page for this

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);
}

I used database-first method. I have created all other part and it is working correctly when I enter values to the table from database. But what I want to achieve is to store the foreign key values 'MovieId' and 'GenreId' to the 'MovieGenre' table when creating a new movie.

This is the code in create action method. How can I store the 'MovieId' and 'GenreId' to the 'MovieGenre' table from this code?

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);
}

Below is the create Action view code, here I used check boxes for the Genre, I want to enter the GenreId from this somehow to the associate table too.

<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");}
}

But what I want to achieve is to store the foreign key values 'MovieId' and 'GenreId' to the 'MovieGenre' table when creating a new movie.

You don't really need MovieId because it is auto-generated when SaveChanges{Async} is called, thus is available only after that call.

But you have explicit join entity MovieGenre with both navigation and explicit FK properties, so you can utilize the navigation property to specify the new Movie and let EF Core handle the actual FK for you. For the other FK you can just assign the existing Genre key (Id).

There are two ways to add a new MovieGenre record in this scenario. Both require creating MovieGenre instance and filling in the navigation and FK properties:

var movieGenre = new MovieGenre
{
    Movie = movies,
    GenreId = genreId // ?? - see below
};

Just not sure where GenreId is coming from here

Create([Bind("MovieId,Title,Description,Storyline,Year,ReleaseDate,Runtime,MovieType, GenreId")] Movie movies

since the Movie class doesn't have GenreId property, so you have to figure that out (eventually revisit the DTO/ViewModel used for communication with the controller).

Once you have that, you either add it to the Movie.MovieGenre collection:

movies.MovieGenre = new List<MovieGenre> { movieGenre };
_context.Add(movies);

or just add it directly to the db context (set):

_context.Add(movies);
_context.Add(movieGenre);

For this particular scenario the explicit join entity helps a lot. If you instead used the EF Core 5.0+ implicit join entity, implementing that operation would require a different approach.

I have found the right code for this. If anyone need the solution here my GitHub repo with the complete code.

https://github.com/Iam-Goku/ProjectMovie.git

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM