0% found this document useful (0 votes)
100 views

Mapping Relationships in EF Core: Julie Lerman

This document discusses various relationship types in Entity Framework Core including one-to-many, many-to-many, and one-to-one relationships. It explains how EF Core interprets these relationships by convention but also how they can be configured. Specific topics covered include mapping additional data in join entities, migrating relationships to reflect model changes, and adding a new one-to-one relationship between existing classes.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
100 views

Mapping Relationships in EF Core: Julie Lerman

This document discusses various relationship types in Entity Framework Core including one-to-many, many-to-many, and one-to-one relationships. It explains how EF Core interprets these relationships by convention but also how they can be configured. Specific topics covered include mapping additional data in join entities, migrating relationships to reflect model changes, and adding a new one-to-one relationship between existing classes.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Mapping Relationships in EF Core

Julie Lerman
MOST TRUSTED AUTHORITY ON ENTITY FRAMEWORK

@julielerman thedatafarm.com
Learning more about one-to-many
relationships
Module
Understanding many-to-many
Overview relationships
Tracking additional data in a join entity
Adding a one-to-one relationship
Visualize the model with EF Core Power
Tools
Migrating the database to reflect model
changes
Learning More About
One-to-Many Relationships
One Samurai Character Can Have Many Quotes
!
?
####

@@@
Convention Over Configuration
Default behavior that can be overridden using
configurations.
public class Samurai
List<Child> {
in Parent public int Id { get; set; }
public string Name { get; set; }
public List<Quote> Quotes { get; set; }
}
Child needs no public class Quote
references back to {
Parent not required public int Id {get;set;}
for EF Core to public string Text {get;set;}
}
understand 1:*
relationship
public class Samurai
List<Child> {
in Parent public int Id { get; set; }
public string Name { get; set; }
public List<Quote> Quotes { get; set; }
}

public class Quote


Child has a {
navigation public int Id {get;set;}
property back to public string Text {get;set;}
public Samurai Samurai {get;set;}
parent. Property is }
required by default.
public class Samurai
List<Child> {
public int Id { get; set; }
in Parent public string Name { get; set; }
public List<Quote> Quotes { get; set; }
}

public class Quote


Child has {
navigation public int Id {get;set;}
property back to public string Text {get;set;}
public Samurai Samurai {get;set;}
parent and a public int SamuraiId {get;set;}
property }
recognized as FK
public class Quote
{
public int Id {get;set;}
public string Text {get;set;}
public Samurai Samurai {get;set;}
public int SamuraiFK {get;set;}

Watch Out for Non-Conventional FK Properties


EF Core will see SamuraiFK as a random int column

And EF Core will infer a FK column named SamuraiId

You can override with mappings, to configure SamuraiFK as the foreign key
public class Samurai
{
List<Child> public int Id { get; set; }
in Parent public string Name { get; set; }
public List<Quote> Quotes { get; set; }
}
Child’s (properly
named) FK public class Quote
property with no {
public int Id {get;set;}
navigation is public string Text {get;set;}
recognized as FK public int
Samurai Samurai
SamuraiId {get;set;}
{get;set;}
}
public class Quote t Only a navigation property to Samurai
{ You must have a samurai object to
public int Id {get;set;} connect a quote
public string Text {get;set;} samurai.Quotes.Add(thequote)
public Samurai Samurai {get;set;}
thequote.Samurai=someobject
}

public class Quote


t With a foreign key property you don’t
{ need a samurai object
public int Id {get;set;}
public string Text {get;set;} thequote.SamuraiId=1
public Samurai Samurai {get;set;}
public int SamuraiId {get;set;}
}

public class Quote t And you can even eliminate the


{ navigation property if your logic
public int Id {get;set;} doesn’t need it
public string Text {get;set;}
public int SamuraiId {get;set;}
}
Will I ever retrieve a Quote
and want to know who said it?
Quote.Samurai.Name
A Few Configuration Examples

modelBuilder.Entity<Samurai>()
modelBuilder.Entity<Samurai>() .HasMany(s => s.Quotes)
.HasMany(s => s.Quotes) .WithOne(q => q.Samurai)
.WithOne(q => q.Samurai) .HasForeignKey(q => q.SamuraiFK);
.HasForeignKey(q => q.SamuraiFK);
EF Core’s Default Many-to-Many Mapping
Many-to-Many support
has changed dramatically in
EF Core 5
Many-to-Many with Skip Navigations

Samurai Battle

List<Battle> List<Samurai>
EF Core 5 Can Interpret Skip Navigations

Join Ends with Class Properties Relational Database: Join Table

Samurai Battle Samurais BattleSamurai Battles


List<Battle> List<Samurai>
SamuraiId SamuraiId BattleId
BattleId
Many-to-Many with Join Entities

Explicit Join Entity Relational Database: Join Table

Samurai Battle Samurais BattleSamurai Battles


List<BattleSamurai> List<BattleSamurai>
SamuraiId SamuraiId BattleId
BattleSamurai BattleId
SamuraiId
BattleId
The way EF Core 5 handles
many-to-many is much
smarter and more flexible
than EF6
EF Core 5’s New Many-to-Many Support

Smarter & more


Much simpler
flexible than
than EF Core 1-3
EF6
SSMS Diagram of SamuraiAppData Tables
Storing Additional Data with
Many-to-Many Payloads
This is a little more
advanced, but a common
and important capability.
Adding More Info to the Relationship

Samurai Kikuchiyo Battle of Anegawa


Adding More Info to the Relationship

When?
Samurai Kikuchiyo Battle of Anegawa
Many-to-Many Relationship

Join Ends with Class Properties Relational Database: Join Table

Samurai Battle Samurais BattleSamurai Battles


List<Battle> List<Samurai>
SamuraiId SamuraiId BattleId
BattleId
Many-to-Many Relationship with Payload

Explicit Join Table with Payload Relational Database: Join Table

Samurai BattleSamurai Battle Samurais BattleSamurai Battles


List<Battle> SamuraiId List<Samurai> SamuraiId SamuraiId BattleId
BattleId BattleId
JoinDate JoinDate
With EF Core 5, the
addition of a join entity will
not complicate EF’s
understanding of your
relationship
The Path of Least Resistance
CODE Magazine
Code Focus Nov 2020
codemag.com/Article/2010042
Source: #wocintechchat
flickr.com/photos/wocintechchat
Many-to-Many Relationship with Payload

Explicit Join Table with Payload Relational Database: Join Table

Samurai BattleSamurai Battle Samurais BattleSamurai Battles


List<Battle> SamuraiId List<Samurai> SamuraiId SamuraiId BattleId
BattleId BattleId
JoinDate JoinDate
Many-to-Many Relationship with Payload
You must configure the DbContext
to understand this mapping

Explicit Join Table with Payload Relational Database: Join Table

Samurai BattleSamurai Battle Samurais BattleSamurai Battles


Configuring the Many-to-Many Payload
Configuring the Join Entity

Identify the
known
many-to-many
relationship
Configuring the Join Entity

Add more
Identify the information
known to that mapping
many-to-many
relationship
modelBuilder
.Entity<End1>
.HasMany(e1=>e1.E2List )
.WithMany(e2=>e2.E1List)

Express *:* Using HasMany/WithMany


End #1 HAS MANY End #2s via the list navigation property.

That other end also is WITH MANY of End1, represented by the E1 list property

Start with either end. There is no difference.


Migrating the Many-to-Many Payload
HasColumnName Fluent Mapping

modelBuilder.Entity<BattleSamurai>()

.Property(bs => bs.SamuraiId).HasColumnName("SamuraisId");

modelBuilder.Entity<BattleSamurai>()

.Property(bs => bs.BattleId).HasColumnName("BattlesBattleId");


Table Mapping Conventions

t DbSet drives table name (Samurais)


public DbSet<Battle> Battle
{get;set;}

t If there is no DbSet, then table uses


public class BattleSamurai the name of the class (BattleSamurai)
{
}

t Override with ToTable mapping


modelBuilder
.Entity<BattleParticipant>()
.ToTable(“BattleSamurai”)
Adding a One-to-One Relationship
Introducing a
new class:
Horse
Dependent End of 1:1 is Always Optional

Samurai can have a horse Samurai can be without a horse


Dependent Default: Must Have a Parent

Additional Considerations

Integer FK is non-nullable by default

Allow “orphaned” horses with nullable


foreign key or a mapping

EF Core can usually determine principal


& dependent

Fluent API mappings can be used to


adjust EF Core’s conventional
interpretation
Horse must have a Samurai
Visualizing How EF Core Sees Your Model
One-to-One Table Mappings

Default Advanced
Dependent gets its own table Dependent data in principal table
Learned more about 1:* relationships
Learned about EF Core 5’s conventional
Review many-to-many support
Implemented a *:* with payload data

Review
Learned about 1:1 defaults e.g., optional
dependents and separate tables
Visualized model with EF Core Power Tools
More tricks with Fluent API and migrations
Migrated database to apply model changes
Coming Up
Interacting with your
EF Core data model
and logging
Resources
Entity Framework Core on GitHub github.com/dotnet/efcore

EF Core Documentation docs.microsoft.com/ef

EF Core Power Tools on GitHub github.com/ErikEJ/EFCorePowerTools/wiki

Entity Framework Community Standup - Many-to-Many in EF Core 5.0


youtube.com/watch?v=W1sxepfIMRM

Pluralsight EF Core 2: Mappings (includes Explicit Join Entity Mapping) bit.ly/2LppcMj


Mapping Many-to-Many
and One-to-One Relationships

Julie Lerman
MOST TRUSTED AUTHORITY ON ENTITY FRAMEWORK

@julielerman thedatafarm.com

You might also like