Home > Software design >  Insert to autogenerated Bridge table in EF Core ASP.NET Core Razor Pages .NET6
Insert to autogenerated Bridge table in EF Core ASP.NET Core Razor Pages .NET6

Time:12-17

I am new to EF and need help in understanding the following: I have a Class table and a students table in database. One Class can have many students and one student can be in many classes. I have one autogenerated table by EF core called ClassModelStudent. It has following fields:

ClassModelStudentTable

I have created a razor page to create the class and on post event , the button should send ClassID and redirect to AddStudents page . enter image description here

Following is the code for AddStudents Class:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using TestProject.Model;

namespace TestProject.Pages.Classes
{
    public class EnrollmentModel : PageModel
    {
        private readonly TestProject.Data.TestProjectContext _context;

    public EnrollmentModel(TestProject.Data.TestProjectContext context)
    {
        _context = context;
    }
    [BindProperty]
   public Enrollment Enrollments { get; set; }   
    public SelectList Classes { get; set; }    
    public IList<Student> UserProfile { get; set; }
    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }
    public async Task OnGetAsync()
    {
        var students = from s in _context.User_Profile
                       select s;
        if (!string.IsNullOrEmpty(SearchString))
        {
            students = students.Where(s => s.FirstName.Contains(SearchString));
        }

        UserProfile = await students.ToListAsync();

        var classes = from i in _context.Class
                          orderby i.Description
                          select i;

        Classes = new SelectList(classes, "ClassID", 
"Description");

    }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {

            return Page();
        }
       //THIS IS WHERE I TRIED ACCESSING CLASSMODELSTUDENT TABLE 
      //AND THE CONTEXT DID NOT SEE IT
       // _context.e
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

}

I have currently connected it to Enrollments table. I am not even sure that if it should write it to the autogenerated table ClassModelStudents or manually created Enrollments? Enrollments table looks like the following:

Enrollment table

In AddStudents page, I am showing the list of students in a table. I have created 'Add To Class' button in each row of the table. And I want to add that student to the selected class when 'add to class' button is clicked. I should be writing to ClassModelStudents table. Please see below the screenshot of AddStudents Page: AddStudents

The thing I am not understanding is how to create the class (Model) for ClassModelStudent? As I cannot access this table directly using context. How to access this table to write the ClassID and StudentID to it?

Please advise.. I would really appreciate your assistance..

following is my model class for ClassModel:

 public class ClassModel

{
    [Key]
    [Required]
    [Display(Name ="Class ID")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ClassID { get; set; }
    //[ForeignKey("UserProfile")]
    //[Display(Name = "User ID")]
    //public virtual int ID { get; set; }
    [Required]
    public string Description { get; set; } 
    [Required]
    public int Occurence { get; set; }
    [Required]
    [DataType(DataType.Date)]
    public DateTime Startdate { get; set; }
    [Required]
    [DataType(DataType.Time)]
    public DateTime From { get; set; }
    [Required]
    [DataType(DataType.Time)]
    //[GreaterThanOrEqualTo("From")]
    public DateTime To { get; set; }
    [Required]
    [DataType(DataType.Currency)]
    public double Fees { get; set; }

    [DisplayFormat(NullDisplayText = "No Instructor Assigned")]
    [ForeignKey("InstructorID")]
    public virtual int InstructorID { get; set; }
    public Instructor? Instructor { get; set; }

    [DisplayFormat(NullDisplayText = "No Student Assigned")]
    public ICollection<Student>? Students { get; set; }

    public ICollection<Enrollment>? Enrollment  { get; set; }
}

THIS Is Enrollments class model:

public class Enrollment
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int EnrollmentID { get; set; }
    [Required]

    [ForeignKey("ClassID")]
    public virtual int ClassID { get; set; }
    [Required]
    [ForeignKey("StudentID")]
    public virtual int StudentID { get; set; }
    [Required]
    public ClassModel? Class { get; set; }
    [Required]
    public Student? Student { get; set; }

    

}

Below is Student Model:

public class Student
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Display(Name = "StudentID")]
    public int StudentID { get; set; }
    [Required]
      
    public string FirstName { get; set; }

    [Required]

    public string LastName { get; set; }
   
    
    [Required]
    public Boolean Status { get; set; }
    [DataType(DataType.Date)]
    public DateTime DateOfBirth { get; set; }
    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }
    [Required]
    [Phone]
    [DataType(DataType.PhoneNumber)]
    public string PhoneNumber { get; set; }

    public string EmergencyContactName { get; set; }
    [Phone]
    [DataType(DataType.PhoneNumber)]
    public string EmergencyContactNumber { get; set; }

    [Required]
    public string Gender { get; set; }

    public string FullName
    {
        get { return LastName   ", "   FirstName; }
    }
    [DisplayFormat(NullDisplayText = "No Class Assigned")]
    public ICollection<ClassModel>? Classes { get; set; }

    public ICollection<Enrollment>? Enrollments { get; set; }    
}

I do not have the code for ClassModelStudent as it is autogenerated.

CodePudding user response:

When you create many-to-many relationship in TestProjectContext,Do you write the code just like :

    .......

    public Dbset<Class> classes;
    public Dbset<students> students;

The ClassModelStudent table is automatically generated by EF core,so you can't use _context.ClassModelStudent to insert any data?

If your problem is like I mentioned above , you can use another method to create many-to-many relationship , I write a simply demo:

Model

 public class Group
    {
        public int Id { get; set; }
        public string GroupName { get; set; }
        public List<GroupMembers> GroupMembers { get; set; }
    }

public class User
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public List<GroupMembers> GroupMembers { get; set; }
    }

public class GroupMembers
    {
        public int Id { get; set; }
        public int UserId { get; set; }
        public User user { get; set; }

        public int GroupId { get; set; }
        public Group group { get; set; }
    }

DataContext

public class WebTestContext : DbContext
    {
        public WebTestContext(DbContextOptions<WebTestContext> options):base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<GroupMembers>()
                .HasKey(gm => new { gm.UserId, gm.GroupId });
            modelBuilder.Entity<GroupMembers>()
                .HasOne(gm => gm.group)
                .WithMany(group=> group.GroupMembers)
                .HasForeignKey(gm => gm.GroupId);
            modelBuilder.Entity<GroupMembers>()
                .HasOne(gm => gm.user)
                .WithMany(user => user.GroupMembers)
                .HasForeignKey(gm => gm.UserId);
        }
        public DbSet<User> usertable { get; set; }
        public DbSet<Group> grouptable { get; set; }
        public DbSet<GroupMembers> GroupMembers { get; set; }
    }

In this way to create many-to-many relationship in DataContext , you can use _context.(Relational tables) in pagemodel.

===========================================================

If Enrollment table is the Relational tables of the ClassModel and Student, It's No need to let the EF core create other relational table.

Model

public class ClassModel
    {
        [Key]
        public int ClassID { get; set; }
        public string Description { get; set; }
        public string ClassName { get; set; }
        
        public ICollection<Enrollment>? Enrollments { get; set; }
    }

public class Enrollment
    {
        [Key]
        public int EnrollmentID { get; set; }
        

        [ForeignKey("ClassID")]
        public virtual int ClassID { get; set; }
        [Required]
        [ForeignKey("StudentID")]
        public virtual int StudentID { get; set; }
        [Required]
        public ClassModel? Class { get; set; }
        [Required]
        public Student? Student { get; set; }
    }

public class Student
    {
        [Key]
        public int StudentID { get; set; }
        public string FirstName { get; set; }
        public string Email { get; set; }

        public ICollection<Enrollment>? Enrollments { get; set; }
    }

TestProjectContext

public class TestProjectContext : DbContext
    {
        public TestProjectContext(DbContextOptions<TestProjectContext> options) : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Enrollment>()
                .HasKey(gm => new { gm.ClassID, gm.StudentID });
            modelBuilder.Entity<Enrollment>()
                .HasOne(gm => gm.Class)
                .WithMany(group => group.Enrollments)
                .HasForeignKey(gm => gm.ClassID);
            modelBuilder.Entity<Enrollment>()
                .HasOne(gm => gm.Student)
                .WithMany(user => user.Enrollments)
                .HasForeignKey(gm => gm.StudentID);
        }

        public DbSet<ClassModel> ClassModels { get; set; }
        public DbSet<Student> students { get; set; }
        public DbSet<Enrollment> enrollments { get; set; }
    }

Then , you just have three tables

enter image description here

you can use any of them in PageModel

enter image description here

  • Related