0

How do I stop EF Core creating a name like this? I have a table with students and workouts I have them setup for EF Core to make the link table as such. I'm using EF Core 5.09. I was following the book example

https://www.learnentityframeworkcore.com/configuration/one-to-many-relationship-configuration

But I think something went wrong if it created a name like that

public class StudentClasses
{
    public int StudentId { get; set; }
    public Students Students { get; set; }
    public int ClassId { get; set; }
    public Classes Classes { get; set; }
}

Then in OnModelCreating override, I have the following:

modelBuilder.Entity<StudentClasses>()
            .HasKey(bc => new { bc.StudentId, bc.ClassId });

modelBuilder.Entity<StudentClasses>()
            .HasOne(bc => bc.Students)
            .WithMany(b => b.StudentClasses)
            .HasForeignKey(bc => bc.StudentId);

 modelBuilder.Entity<StudentClasses>()
             .HasOne(bc => bc.Classes)
             .WithMany(c => c.StudentClasses)
             .HasForeignKey(bc => bc.ClassId);

But this results in a awful naming convention in the database.

enter image description here

How do I make it that it just shows ClassId as the name of the foreign key I fixed the spelling mistake in code, but I don't know how to stop the classes before it. It's a one Student can belong to many classes relationship.

My Students class

public class Students
{  
    [Key]
    public int StudentId { get; set; }
    public int? Type { get; set; }
    public string? FirstName { get; set; }
    public string? Surname { get; set; }
    public DateTime? DOB { get; set; }
    public decimal? Weight { get; set; }
    public decimal? Height { get; set; }
    public int? Gender { get; set; }
    public string? Age { get; set; }

    public ICollection<StudentWorkouts> StudentWorkouts { get; set; }
    public ICollection<StudentClasses> StudentClasses { get; set; }
    public bool? IsDeleted { get; set; }
    public bool? IsActive { get; set; }
    public string? CreatedBy { get; set; }
    public string? LastModifiedBy { get; set; }
    public DateTime? LastUpdatedDate { get; set; }
    public DateTime? CreatedDate { get; set; }
}

My Classes class - no pun intended:

public class Classes
{
    [Key]
    public int ClassedId { get; set; }
    public Guid? UserId { get; set; }
    public ICollection<Students> Students { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public ICollection<StudentClasses> StudentClasses { get; set; }
    public bool? IsDeleted { get; set; }
    public bool? IsActive { get; set; }
    public string? CreatedBy { get; set; }
    public string? LastModifiedBy { get; set; }
    public DateTime? LastUpdatedDate { get; set; }
    public DateTime? CreatedDate { get; set; }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
c-sharp-and-swiftui-devni
  • 3,743
  • 4
  • 39
  • 100
  • Maybe this can help you get an idea [How can I set the foreign key name using the Fluent API with Code First Migrations?](https://stackoverflow.com/questions/59363602/how-can-i-set-the-foreign-key-name-using-the-fluent-api-with-code-first-migratio) ? – GoWiser Sep 20 '21 at 00:27
  • I don' t understand what is that foreign key for since you have a many-to-many table. I think you can delete it. It must be from the previous db structure. – Serge Sep 20 '21 at 00:41
  • Why does your `Classes` have a `Students` navigation? That's why EF Core is generating a new shadow property. Are you trying to define a skip navigation? (https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#many-to-many) – Jeremy Lakeman Sep 20 '21 at 01:47
  • No am not trying to skip it i was following that tutorial – c-sharp-and-swiftui-devni Sep 20 '21 at 03:23

1 Answers1

0

The bit that looks to be screwing you up is:

public ICollection<Students> Students { get; set; }

The relationship that EF will be trying to establish here is a key in Students to point back to classes. Hence a ClassesClassId derived from the ClassId in the Classes entity.

If you want the students for a class, you should not be doubling up between Classes.StudentClasses and Classes.Students.

Your example appears to be a textbook many-to-many relationship.

If you are using EF Core 5 then you can now avoid needing to declare the StudentClass entity entirely:

public class Student
{
    // ...
    public virtual ICollection<Classes> Classes { get; set; } = new List<Classes>();
    // ...
}

public class Classes
{
    // ...
    public virtual ICollection<Student> Students { get; set; } = new List<Students>();
    // ...
}

EF will automatically generate the joining table, or you can map an explicit joining table/entity.

EF Core 2/3.1 required joining entities to be declared and directly referenced, much like the example you are following. This isn't a many-to-many relationship but rather a 1-to-many-to-1 relationship.

A more up to date reference if you are using EF Core 5: https://www.thereformedprogrammer.net/updating-many-to-many-relationships-in-ef-core-5-and-above/

Explicit mapping and use of a joining entity is usually only required if you want to access non-key properties on the joining entity. For example if you have properties or relationships specific to a StudentClass entity that you want to access, or need to populate when working with students and/or classes. If the table is merely a StudentId & ClassId, then it's typically preferable to just work with a student's classes collection through Student.Classes rather than Student.StudentClasses.Select(sc => sc.Class).ToList().

If you're using EF Core 2 or 3.1 then you're essentially stuck with using the joining entity 1-to-many-to-1 relationship. I would highly recommend pushing to update to EF Core 5 as IMHO EF Core 3.1 is still a dog's breakfast of unimplemented features from EF6. :)

Steve Py
  • 26,149
  • 3
  • 25
  • 43
  • Do I no longer ned my onmodel creating as well then – c-sharp-and-swiftui-devni Sep 20 '21 at 07:33
  • U say it doesnt need the table yet that article still shows the creation of BookTags does it no longer need to be in dbcontext level. – c-sharp-and-swiftui-devni Sep 20 '21 at 07:53
  • It doesn't necessarily need to reference the joining "entity", it still creates the joining table behind the scenes. I'd need to refresh my memory with EF Core 5 as to whether the entity still needs to be declared for the mappings or if you can just map the table definition (table name, column names) or let it manage the table entirely behind the scenes as it worked with EF6. You don't need to declare a `DbSet` of StudentClasses in either case, even if you declare a StudentClasses entity class. – Steve Py Sep 20 '21 at 11:16