ForeignKey Attribute in Entity Framework Core

ForeignKey Attribute in Entity Framework Core

In this article, I will discuss the ForeignKey Data Annotation Attribute in Entity Framework Core (EF Core) with Examples. Please read our previous article discussing the Key Attributes in Entity Framework Core with Examples. Before understanding ForeignKey Attribute in EF Core, let us first understand what is a Foreign Key in a database.

What is a Foreign Key Constraint in a Database?

Creating relationships between database tables is one of the important concepts in databases. This mechanism facilitates linking data stored in various tables, making retrieving information easier and more efficient.

To connect two database tables or to establish a relationship between two database tables, a Foreign Key must be specified in one table that refers to a unique column (either a Primary Key or Unique Key) in the other table. This Foreign Key constraint binds the two database tables together and verifies the presence of data from one table in the other. A Foreign Key in one table points to a primary or unique key in another table.

ForeignKey Attribute in Entity Framework Core:

In Entity Framework Core (EF Core), the ForeignKey Attribute is used to configure the relationship between two entities. This attribute overrides the EF Core’s default foreign key convention, which is followed otherwise. By default, Entity Framework Core searches for a foreign key property in the Dependent Entity with the same name as the primary key property in the Principal Entity.

In Entity Framework Core (EF Core), the ForeignKey attribute is used to specify which property serves as the foreign key in a relationship between two entities. This attribute comes in handy, especially when the convention-based naming isn’t followed, and you want to make it explicit to EF Core about the relationship.

What is a Dependent Entity and a Principal Entity in Entity Framework Core?

In the context of Entity Framework Core (EF Core) and relational databases in general, the terms “Dependent Entity” and “Principal Entity” are often used when discussing relationships between entities, particularly in the context of foreign key relationships.

  • Principal Entity: This is the entity on the “one” side of a relationship. It can exist independently of the dependent entity. In most scenarios, the principal entity’s primary key will be used as the foreign key in the dependent entity.
  • Dependent Entity: This is the entity on the “many” side or the entity that holds the foreign key reference. It has a dependency on the principal entity because it cannot exist without a reference to the principal entity (unless the foreign key is nullable).
Examples to Understand Default ForeignKey Convention in Entity Framework Core:

In Entity Framework Core, a Relationship always involves two endpoints. Each endpoint must provide a navigational property that maps to the other end of the relationship. For a better understanding, consider Standard Entity, which serves as our Principal Entity, with StandardId as the Primary Key Property. Note that we have a mandatory collection navigational property called “students” that is necessary for implementing Foreign Key Relationships using EF Core.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Standard
    {
        public int StandardId { get; set; }
        public string? StandardName { get; set; }
        public string? Description { get; set; }
        public ICollection<Student>? Students { get; set; }
    }
}

Next, modify the Student Entity as follows. In our example, the Student Entity is the Dependent Entity. Note that we have included the Standard Reference Navigational Property, which is mandatory for establishing the Foreign Key in the Student database table. Additionally, we have included the StandardId property, which refers to the Primary Key Property of the Standard table.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        //The Following Property Exists in the Standard Entity
        public int StandardId { get; set; }
        //To Create a Foreign Key it should have the Standard Navigational Property
        public Standard? Standard { get; set; }
    }
}

In this example, we will demonstrate the one-to-many relationship between the Student and Standard Entities. This relationship is represented by including StandardId in the Student class, which has a reference property called Standard. Meanwhile, the Standard entity class includes a collection navigation property called Students. The StandardId property in the Student Class matches the primary key property of the Standard class. As a result, the StandardId property in the Student class will automatically become a Foreign Key Property, and the corresponding column in the database table will also become a Foreign Key Column.

Note: You must remember that both Entities should and must have Navigational Properties to implement Foreign Key Relationships. In our example, the Student Entity has the Standard Reference Navigational Property, and the Standard Entity has the Students collection Navigation Property, which will establish the one-to-many relationship between these two entities. That means one student has one standard, and one standard can have multiple students. Next, modify the EFCoreDbContext as follows:

using Microsoft.EntityFrameworkCore;
namespace EFCoreCodeFirstDemo.Entities
{
    public class EFCoreDbContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=LAPTOP-6P5NK25R\SQLSERVER2022DEV;Database=EFCoreDB;Trusted_Connection=True;TrustServerCertificate=True;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        }

        public DbSet<Student>Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

Note: Please delete the EFCoreDB database from the SQL Server using SSMS if it already exists, and then also delete the Migration folder from your project if it exists.

As we already discussed, whenever we add or update domain classes or configurations, we need to sync the database with the model using add-migration and update-database commands using Package Manager Console or .NET Core CLI.

So, open the Package Manager Console and Execute the add-migration and update-database commands as follows. You can give any name to your migration. Here, I am giving DbMig1. The name that you are giving it should not be given earlier.

ForeignKey Data Annotation Attribute in Entity Framework Core (EF Core) with Examples

If you verify the database, the Foreign key should have been created in the Student database, as shown in the image below. Here, the Foreign Key Property is created with the name StudentId.

ForeignKey Data Annotation Attribute in Entity Framework Core (EF Core) with Examples

Suppose the Foreign Key Property does not exist in the Dependent Entity class. In that case, Entity Framework will create a Foreign Key column in the Database table with the Primary Key Property Name of the Principal Entity.

To understand this, modify the Student Entity class as follows. Here, you can see we have not added the StandardId property. So, in this case, Entity Framework will create the Foreign Key with the name StandardId. We must have added the Standard reference navigation Property. Otherwise, the foreign key will not be created.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        //To Create a Foreign Key it should have the Standard Navigational Property
        public Standard? Standard { get; set; }
    }
}

With the above changes in place, open Package Manager Console and Execute the following add-migration and update-database commands as shown below.

ForeignKey Data Annotation Attribute in Entity Framework Core with Examples

If you verify the database, the Foreign key should have been created in the Student database table with StudentId, as shown in the image below.

ForeignKey Data Annotation Attribute in Entity Framework Core with Examples

Entity Framework follows these default conventions to create the Foreign Key column in the database.

What is ForeignKey Attribute in Entity Framework?

The ForeignKey Attribute in Entity Framework Core configures a foreign key relationship between the entities. It overrides the default foreign key convention, followed by EF Core. It allows us to specify the foreign key property in the Dependent Entity whose name does not match the primary key property of the principal entity.

Now, if you go to the definition of ForeignKey Attribute, you will see the following signature. As you can see, this class has one constructor that takes the associated navigation property’s name as an input parameter.

What is ForeignKey Attribute in Entity Framework?

The [ForeignKey(name)] attribute can be applied in three ways:

  1. [ForeignKey(NavigationPropertyName)] on the Foreign Key Scalar Property in the Dependent Entity.
  2. [ForeignKey(ForeignKeyPropertyName)] on the Related Reference Navigation Property in the Dependent Entity.
  3. [ForeignKey(ForeignKeyPropertyName)] on the Collection Navigation Property in the Principal Entity.

Note: Before proceeding further, we must identify the Principal and Dependent entities. In our example, the Standard is the Principal Entity, and the Student is the Dependent Entity; we will create the Foreign Key in the Dependent Entity.

[ForeignKey] on the Foreign Key Scaler Property in the Dependent Entity

The [ForeignKey] Attribute in Entity Framework Core can be applied to the Foreign Key Scalar Property in the Dependent Entity. In this case, we must specify the related Navigation Property name in the ForeignKey.  For a better understanding, please modify the Student Entity as follows. As you can see in the below code, we have applied the [ForeignKey(“Standard”)] on the StandardReferenceId scaler property, which will be created as the Foreign Key in the database pointing to the Standard table StandardId (Primary Key) column.

using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        [ForeignKey("Standard")]
        public int StandardReferenceId { get; set; }
        //Related Standard Navigational Property
        public Standard? Standard { get; set; }
    }
}

With the above changes in place, open the Package Manager Console and Execute add-migration and update-database commands as shown below.

[ForeignKey] on the Foreign Key Property in the Dependent Entity

If you verify the database, the foreign key should have been created in the Student database table with StandardReferenceId, as shown in the image below.

[ForeignKey] on the Foreign Key Property in the Dependent Entity

[ForeignKey] on the Reference Navigation Property in the Dependent Entity

The [ForeignKey] Attribute in EF Core can also be applied to the Reference Navigation Property of the Dependent Entity. In this case, we need to specify the dependent entity foreign key scaler property name in the [ForeignKey] Attribute. For a better understanding, please modify the Student Entity as follows. As you can see, we have StandardReferenceId in the [ForeignKey] Attribute, i.e., [ForeignKey(“StandardReferenceId”)], which is applied to the Standard Navigation Property.

using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        //Related Foreign Key Property
        public int StandardReferenceId { get; set; }

        [ForeignKey("StandardReferenceId")]
        public Standard? Standard { get; set; }
    }
}

In the above example, the [ForeignKey] attribute is applied on the Standard navigation property, and the name of the foreign key scaler property StandardReferenceId is specified. Here, Entity Framework Core will create the foreign key column StandardReferenceId in the Students table in the database.

With the above changes, open Package Manager Console and Execute add-migration and update-database commands as shown below.

[ForeignKey] on the Navigation Property in the Dependent Entity

If you verify the database, the foreign key should have been created in the Student database table with StandardReferenceId, as shown in the image below.

[ForeignKey] on the Navigation Property in the Dependent Entity

[ForeignKey] on the Collection Navigation Property in the Principal Entity

The [ForeignKey] Attribute in EF Core can also be applied to the Collection Navigation Property in the Principal Entity, and the related foreign key scaler property name can be specified in the Dependent Entity. Let us understand this with an example. First, modify the Student Entity as follows. Here, you can see we have removed the ForeignKey Attribute.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public int StandardReferenceId { get; set; }
        public Standard? Standard { get; set; }
    }
}

We want the Property StandardReferenceId to be created as a Foreign Key column in the Students database table, which must be pointed to the StandardId Property of the Standard entity. To do so, modify the Standard Entity as follows. Here, you can see the [ForeignKey] attribute is applied on the Students collection navigation property, and here, we are passing the StandardReferenceId property to the [ForeignKey] attribute, which will make the StandardReferenceId a Foreign Key Property.

using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreCodeFirstDemo.Entities
{
    public class Standard
    {
        public int StandardId { get; set; }
        public string? StandardName { get; set; }
        public string? Description { get; set; }
        [ForeignKey("StandardReferenceId")]
        public ICollection<Student>? Students { get; set; }
    }
}

With the above changes, open Package Manager Console and Execute add-migration and update-database commands as shown below.

[ForeignKey] on the Navigation Property in the Principal Entity

If you verify the database, the foreign key should have been created in the Student database table with StandardReferenceId, as shown in the image below.

[ForeignKey] on the Navigation Property in the Principal Entity

Note: In this article, we have implemented the One-To-Many relationship using EF Core. In our upcoming articles, I will discuss One-to-One, One-to-Many, and Many-to-Many Relationships in detail using Entity Framework Core.

Advantages of ForeignKey Attribute in Entity Framework Core
  • Explicitness: Using the ForeignKey attribute, you clearly clarify which property is being used as a foreign key. This clarity can help other developers who read the code to understand the relationships without inferring them from conventions.
  • Flexibility in Naming: EF Core’s convention for foreign keys relies on specific naming patterns. If you have existing database schemas or prefer a different naming convention, the ForeignKey attribute allows you to map your entities correctly without adhering to the default convention.
  • Composite Foreign Keys: For relationships involving multiple columns (composite keys), the ForeignKey attribute must define which properties are part of the foreign key.
  • Multiple Relationships: In cases where an entity has multiple relationships to another entity (e.g., a Person entity having both Mother and Father navigation properties pointing to another Person), the ForeignKey attribute can help clarify which foreign key property corresponds to which navigation property.
Disadvantages of ForeignKey Attribute in Entity Framework Core:
  • Difficult to Understand: Using the ForeignKey attribute can make your entity classes difficult to understand, especially if you have many relationships to define. This can make the code harder to read and maintain compared to relying on conventions.
  • Inconsistencies in the Codebase: If you are working in a team setting, and some developers use the ForeignKey attribute while others rely on default conventions, it might lead to inconsistencies in the codebase. This can also make the code harder to understand and maintain.
  • Refactoring Concerns: When renaming properties or changing relationships, you must update the ForeignKey attribute’s argument accordingly. It can lead to runtime errors or incorrect database mappings if you forget.
  • Potential for Errors: Manually specifying the foreign key introduces the possibility of mismatches between the navigation property and the specified foreign key, leading to unexpected behavior or errors.

When deciding between using an attribute or conventions, it’s important to consider your scenario and preferences. You should have the clarity and flexibility it provides against the possibility of errors and additional maintenance. If you choose to use the attribute, it’s important to maintain consistency throughout the codebase.

In the next article, I will discuss Index Attributes in Entity Framework Core with Examples. Here, in this article, I try to explain the ForeignKey Data Annotation Attribute in Entity Framework Core with Examples. I hope you enjoyed this ForeignKey Attribute in EF Core with Examples article. Please give your valuable feedback and suggestions about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *