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

table of contents
Hello, I'm Eita
we will organize how relationships are established in Entity Framework Core (EF Core), a .NET ORM
Since I have mainly been developing with Laravel (Eloquent), I had the impression that relationships were something that you had to explicitly define in the model.
In Laravel , you can only treat them as relationships in Eloquent once you define hasMany or belongsTo
However, when I first started using EF Core, I felt a sense of discomfort,
as if relationships were being established even though they weren't written EF Core automatically interprets the relationships between entities from navigation properties and naming conventions.
This means that there are situations where relationships are established even without explicitly stating them.
In this article, we will focus on the conditions for establishing relationships in EF Core
- What determines a relationship?
- What happens if you don't clarify?
Let's take a look
Relationships in EF Core are basically established in three patterns
EF Core relationships are automatically interpreted from the structure of your entity classes.
Typically, relationships are detected in the following three patterns:
1. Navigation only
2. Foreign key only
3. Navigation + Foreign key
*However, if the naming or structure is ambiguous, the relationship may not be detected or an exception may occur
Navigation only
public class Post { public int Id { get; set; } public User User { get; set; } // Navigation }
User , EF Core will interpret this as "navigation to a related entity."
In this case, even if a corresponding foreign key does not exist in the class, EF Core will internally generate a shadow property
Foreign Keys Only
public class Post { public int Id { get; set; } public int UserId { get; set; } // Foreign key }
Properties that fit the conventions, such as UserId, are recognized as
potential foreign keys will be 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 }
Having both foreign key and reference navigation makes it easier for EF Core to interpret the relationship in a convention-based way.
While the relationship itself is valid with just one, having both makes the intent clearer and reduces ambiguity in reasoning.
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)
Conventions are used for this automatic registration .
EF Core determines relationships by combining the following information from an entity class:
- Property name (naming convention)
- Property type (PK compatible type)
- Structure (navigation/collection availability)
Based on these three, a relationship is registered internally
In other words, EF Core is not "not written" but "interpreted according to the conventions"
This is the true nature of relationship formation
Below is a rough summary of what EF Core looks at and how it interprets it based on conventions.
While there are exceptions and individual settings, I think it's useful for getting an overall picture of relationship 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 will not be detected.
- In the case of one-to-one, the subordinate side cannot be determined and an exception may occur.
- When there are multiple navigations, the interpretation may be different from the intention.
There are situations where the behavior is difficult to read
OnModelCreating to explicitly fix the interpretation of relationships .
You can explicitly fix or override the interpretation of conventions such as HasMany / WithOne
*Note: OnModelCreating is not a place exclusively for setting relationships. It is where
you define the entire entity mapping, including table name, column name, primary key, composite key, index, required/optional, number of characters, and conversion (ValueConverter) .
Since the theme this time is relationships, we will focus on relationship settings such as HasMany / WithOne / HasForeignKey
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 does not follow the convention
- I want to define one-to-one relationships reliably
- I want to fix foreign key names
- I want to control Cascade behavior
- I want to eliminate ambiguous relationships (I want to fix the intent)
- I want to improve readability for the team
Once we clarify the relationship between convention and explicit configuration, the relationships in EF Core are determined in the following order:
First, let's take a look at how relationships are determined when building a model for the first time
① 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 personally about
In EF Core, relationships are not inferred every time; the content finalized when the model is first built is cached as 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
So far, we've looked at the process of establishing relationships in EF Core (detection by convention → explicit configuration as needed).
To summarize the differences with Laravel, EF Core is an ORM that does not "establish relationships just by writing them in the model," but rather "interprets class structures by convention and constructs relationships .
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 for FKs , I feel like I'll be able to better understand other ORMs and similar behaviors in the future, while sorting out the source of any discomfort.
That's it!!
2