How to set FK in OnModelCreating() method EF Core

Pablo

Well-known member
Joined
Aug 12, 2021
Messages
79
Programming Experience
10+
Hi all

I have been studying CRUD operations in web applications following tutorials (Blazor, MVC, etc), but none of them uses more than one table in the DB. So now I'm trying to test something like an agenda in a web application. So I have two tables (Models), they are:
1) People:
IdPerson
FullName
EMail
Address

2) Telephone
IdPhone
PhoneNumber
Description
IdPerson

where IdPerson from Telephone is a FK that points to IdPerson, that is PK from People.

My question is how to set this relation (FK_Telephone_People) in the OnModelCreating() method (which is in the class that inherits from DbContext). By now I have this:

C#:
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<People>(table =>
            {
                table.HasKey(col => col.IdPerson);
                table.Property(col => col.IdPerson).UseIdentityColumn().ValueGeneratedOnAdd();
                table.Property(col => col.FullName).HasMaxLength(50);
                table.Property(col => col.EMail).HasMaxLength(40);
                table.Property(col => col.Address).HasMaxLength(50);
            });
            modelBuilder.Entity<Telephone>(table =>
            {
                table.HasKey(col => col.IdPhone);
                table.Property(col => col.IdPhone).UseIdentityColumn().ValueGeneratedOnAdd();
            });
        }

Other question is: Do I have to add a List<Telephone> to the People Model, to be able to display data in the front end, wether it is Blazor, MVC, or wathever?
Note that a Person can have many PhoneNumbers, but they can only have one Person. (Is this called "one to many"?)
Note: I'm trying to create the DB from code, using a Migration and so (Is this called "code first"?).

I would strongly appreciate your valuable help, as usual.
Thanks
Pablo
(Buenos Aires - Argentina)
 
The whole point of EF is so that you don't have to do all that plumbing. You would just setup the class relationships (and follow the EF naming convention), and it will figure out the foreign key relationships for you. But as you've discovered you can also override the default behavior.

Have you looked at the documentation? It shows how to let EF do it for you, as well as how to override or customize:
 
As suggested, you should be setting up your entities by convention to have this done automatically as a first option, e.g.
C#:
    public class Parent
    {
        [Key]
        public long ParentId { get; set; }

        public ICollection<Child> Children { get; set; }
    }

    public class Child
    {
        [Key]
        public long ChildId { get; set; }
        public long ParentId { get; set; }

        public Parent Parent { get; set; }
    }
If I'm not mistaken, that should be enough to have a foreign key with the default configuration created. If you're in a situation where you can't follow those conventions though, you can use the fluent API. We have a situation where we have three tables storing data for three different types of surveys and they all use SurveyId as their PK, which is then also used in first-level child tables that function as sections. Here's an example of how we configure a foreign key over a one-to-many relation between a first- and second-level child table where the parent PK does not follow the standard naming convention:
C#:
modelBuilder.Entity<RapidMonitoringSurveyBenthos>(etb =>
                                                  {
                                                      etb.ToTable(nameof(RapidMonitoringSurveyBenthos));

                                                      etb.HasMany(rmsb => rmsb.RapidMonitoringSurveyBenthosObservations)
                                                         .WithOne(rmsbo => rmsbo.RapidMonitoringSurveyBenthos)
                                                         .HasForeignKey(rmsbo => rmsbo.SurveyId)
                                                         .OnDelete(DeleteBehavior.NoAction)
                                                         .IsRequired();
                                                  });
 
Back
Top Bottom