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:
I have created a razor page to create the class and on post event , the button should send ClassID and redirect to AddStudents page .
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:
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:
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
you can use any of them in PageModel