[C#] Entity Framework Core -Relationship Establishment Conditions-

table of contents
Hello, I'm Eita
the ORM for .NET Entity Framework Core (EF Core) I'll explain how relationships are established in
Up until now, I've mainly developed using Laravel (Eloquent), so I had the impression that relationships were something you "explicitly define and use in the model."
In Laravel hasMany or belongsTo , you can only treat something as a relationship in Eloquent after defining
However, when I first encountered EF Core, I felt"relationships were established even though they weren't explicitly written." a sense of unease because
In EF Core, relationships between entities are automatically interpreted from navigation properties and naming conventions.
In other words, there are situations where relationships are established without explicit declaration.
In this article, we will focus on the conditions for establishing relationships in EF Core
- What determines the relationship?
- What happens if this isn't clearly defined?
Let's take a look
Relationships in EF Core are basically established in three patterns
EF Core automatically interprets relationships from the structure of entity classes.
Typically, relationships are detected in the following three patterns:
1. Navigation only
2. External keys only
3. Navigation + External keys
*However, if the naming or structure is ambiguous, the relationship may not be detected or an exception may occur
Navigationonly
public class Post { public int Id { get; set; } public User User { get; set; } // Navigation }
User is enough for EF Core to interpret it as "navigation to a related entity".
In this case, even if a corresponding foreign key does not exist within the class, EF Core internally a shadow property generates
Foreign Keys Only
public class Post { public int Id { get; set; } public int UserId { get; set; } // Foreign key }
Properties that conform to the convention, such as UserId,potential foreign keysare recognized as
They are treated as relationships even without navigation.
Navigation + Foreign Keys
public class Post { public int Id { get; set; } public int UserId { get; set; } // Foreign key public User User { get; set; } // Navigation }
The presence of both foreign keys and reference navigation makes it easier for EF Core to interpret relationships based on conventions.
While the relationship itself can be established with either one, having both clarifies the intent and reduces ambiguity in inference.
So why is this all it takes? Next, let's take a look behind the scenes
Why does it work? (Mechanism of reasoning)
In short, relationship information is automatically registered in the internal model (IModel) based on the entity class (the class that defines the table structure)
are used for this automated registration process Conventions .
EF Core determines relationships by combining the following information from an entity class:
- Property name (naming convention)
- Property type (type compatible with PK)
- Structure (navigation/collection presence/absence)
Based on these three, a relationship is registered internally
In other words, EF Core doesn't "not write" anything; rather,it "interprets" it according to the rules.
This is the true nature of relationship formation
The following table provides a rough overview of what EF Core looks at and how it interprets it, based on its conventions.
While there are exceptions and individual settings, I think it's quite useful for understanding the overall picture of relational inference.

Conventions and Explicit Configuration - The Role of OnModelCreating
As mentioned earlier, EF Core first automatically "detects and determines" relationships from the entity structure based on conventions
However, while reasoning by convention can reduce the amount of description,
- If the naming is slightly off, it may not be detected.
- One-to-one relationships may be exceptions because the dependent cannot be determined.
- If there are multiple navigations, it may be interpreted differently than intended.
There are situations where the behavior is difficult to read
In situations like these, when you want to explicitly fix the interpretation of a relationship, you use OnModelCreating .
HasMany / WithOne the interpretation of conventions using explicitly fix or override You can
*To clarify,OnModelCreating is not solely for relationship settings. It's where
including table names, column names, primary keys, composite keys, indexes, required/optional fields, character counts, and conversions (ValueConverter)you define the entire entity mapping,.
Since the theme this time is relationships,HasMany , WithOne , and HasForeignKey we'll focus on explaining relationship settings such as
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User> () .HasMany(u => u.Posts) .WithOne(p => p.User) .HasForeignKey(p => p.UserId); }
If you follow the rules, you don't need to write it, but it's worth making it clear in the following cases:
- Naming conventions are not followed
- We want to clearly define one-to-one relationships
- We want to fix foreign key names
- We want to control cascade behavior
- We want to eliminate ambiguous relationships (fix the intent)
- We want to improve readability within the team
Once we clarify the relationship between convention and explicit configuration, the relationships in EF Core are determined in the following order:
First,of how relationships are determined during the initial model building let's look at the process
① Process that runs when building a model for the first time (relation determination flow)
Load entity class structure (Navigation / FK / Naming) ↓ Infer relationships using Convention ↓ Register in internal model (IModel) ↓ OnModelCreating (explicit setting using Fluent API) ↓ Finalize relationships (relationships based on foreign keys)
Also, I was personallyabout when the model definition (IModel) including relations is finalized も気になったので、補足として置いておきます。
In EF Core, relations are not inferred every time; rather,the finalized content during the initial model construction is cached as the IModel and reused thereafter.
② Caching and reusing IModel (per DbContext type)
First time (per DbContext type) ↓ Build and finalize IModel (the entire flow above is executed here) ↓ Cache IModel ↓ Second and subsequent times (same DbContext type) ↓ Get cached IModel ↓ Reuse model (relationship inference / OnModelCreating is generally not re-executed)
summary
Up to this point, we've looked at the process of establishing relationships in EF Core (detection by convention → explicit configuration as needed), while organizing the information.
To summarize the differences from Laravel in one sentence, EF Core is an ORM that doesn't "establish relationships simply because you write them in the model," but rather "builds relationships by interpreting the class structure using conventions .
On the other hand, regardless of whether you're using EF Core or Laravel, foreign keys (FKs) are crucial for establishing relationships at the database level.
these ORM-specific conventions and auto-completion rules around FKs will make it easier to understand and address any inconsistencies when encountering other ORMs or similar behaviors in the future.
That's it!!
3
