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

defining-one-to-many-relationships-slides

Uploaded by

ahmed11611612
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views

defining-one-to-many-relationships-slides

Uploaded by

ahmed11611612
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Defining One-to-Many

Relationships

Julie Lerman
EF Core Expert and Software Coach

@julielerman | thedatafarm.com
Install a tool to visualize the data model

Module How EF Core interprets various one-to-


many setups
Overview
Benefits of foreign key properties
Modify the entity classes
Seed related data
Use migrations to evolve the database to
match a modified model
Using mappings to guide EF Core when
needed
Visualizing EF Core’s Interpretation of
Your Data Model
How EF Core Determines Mappings to DB

d er
min
R e
Override with Override with
Conventions Fluent Mappings Data Annotations
Default assumptions Apply in DbContext
Apply in entity
using Fluent API

property name=column name modelBuilder.Entity<Book>() [Column(“MainTitle")]


.Property(b => b.Title) public string Title{get;set;}
.HasColumnName(“MainTitle");
EF Core Power Tools (Visual Studio) Extension

And open source at: github.com/ErikEJ/EFCorePowerTools


Interpreting One-to-Many Relationships
One Author Can Have Many Books
Convention Over Configuration
Default behavior that can be overridden using configurations.
One-to-Many in the Database

Views from SQL Server Management Studio


Shadow Properties
Properties that existing the data model but not the entity class. These
can be inferred by EF Core or you can explicitly define them in the
DbContext.
Relationship Terminology

Parent / Child Principal / Dependent


Reference from parent
to child is sufficient

public class Author


{ t List<Child> in Parent
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Book> Books { get; set; }
}

public class Book


{
t This Child has no references back to Parent
public int Id { get; set; } t Foreign Key (e.g, AuthorId) will be inferred
public string Title { get; set; } in database
}
Child has navigation prop
pointing to Parent

public class Author


{ t List<Child> in Parent
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Book> Books { get; set; }
}

public class Book t This child has a reference back to parent aka
{ “Navigation Property”
public int Id { get; set; } t It already understands the one-to-many
public string Title { get; set; } because of the parent’s List<Child>
public Author Author { get; set; } t The reference back to parent aka
} “Navigation Property” is a bonus
t AuthorId FK will be inferred in the database
FK is recognized because
of reference from parent

public class Author


{ t List<Child> in Parent
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Book> Books { get; set; }
}

public class Book


{ t AuthorId is recognized as foreign key for
public int Id { get; set; } two reasons:
public string Title { get; set; } 1) the known relationship from parent
public int AuthorId {
{get;
get; set;
set; }} 2) follows FK naming convention (type + Id)
}
Child has navigation prop
pointing to Parent & an FK

public class Author


{ t List<Child> in Parent
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Book> Books { get; set; }
}

public class Book


{ t One to many is known because of List<Child>
public int Id { get; set; } t Navigation and FK are bonus
public string Title { get; set; }
public Author Author { get; set; }
public int AuthorId {get;set;}
}
No detectable relationship

public class Author t Parent has no knowledge of children


{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class Book


{
public int Id { get; set; }
public string Title { get; set; }
public int AuthorId {get;set;} t This AuthorId property is just a random integer
}
You can achieve so
much with
mappings
Here’s a peek at an example:
mapping a relationship that is
completely unconventional.
Configuring a One-to-Many
When convention can’t discover it because there are no references

PubContext.cs

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Author>()
.HasMany<Book>()
.WithOne();
}
Benefitting from Foreign Key Properties
Foreign Key properties
are your friends.

And sometimes, navigations


are just in the way.
Tying a Book to an Author the Easy Way

mybook.AuthorId=23
When/Why Ditch Navigation to the
Parent?
Considering the Parent Navigation Property

Coming from EF Core is now smarter about missing


earlier versions? navigation data, but not in all scenarios.

Tip: Default to no
Only add it if your biz logic requires it!
navigation property
Why have FK property?
public class Book t Only a navigation property to Author.
{ You must have an author in memory to
public int Id {get;set;} connect a book.
public string Title {get;set;} author.Books.Add(abook)
public Author Author{get;set;} abook.Author=someauthor
}

public class Book


t With a foreign key property, you don’t
{ need an Author object.
public int Id {get;set;}
public string Title {get;set;} book.AuthorId=1
public Author Author{get;set;}
public int AuthorId {get;set;}
}

public class Book t ...and you can even eliminate the


{ navigation property if your logic doesn’t
public int Id {get;set;} need it.
public string Title {get;set;}
public int AuthorId {get;set;}
}
Foreign Key Properties & HasData
Seeding
HasData requires explicit primary and foreign key
values to be set. With AuthorId now in Book, you
can seed book data as well.
modelBuilder.Entity<Author>().HasData(new Author {Id=1, FirstName=“Julie”, .. };
modelBuilder.Entity<Book>().HasData(
new Book {BookId=1,AuthorId=1,Title=“Programming Entity Framework”});

Seeding Related Data


Provide property values including keys from and foreign keys from “Parent”
HasData will get interpreted into migrations
Inserts will get interpreted into SQL
Data will get inserted when migrations are executed
My Author & Book Key Properties Use
Different Naming Conventions!
That’s not a recommended coding practice.
Let’s fix it.
Changes to My Model

Added AuthorId foreign key property to book

Added seed data for books via HasData in PubContext

Modified the Author’s key property from Id to AuthorId


Mapping Unconventional Foreign Keys
Following along with code?

I’ve reverted experiments


from previous clips!
EF Core should not drive
how you design your
business logic
Configuring a Non-Conventional Foreign Key
FK is tied to a relationship, so you must first describe that relationship

PubContext.cs

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Author>()
.HasMany(a => a.Books)
.WithOne(b => b.Author)
.HasForeignKey(b => b.AuthorFK);
}
Understanding Nullability and Required
vs. Optional Principals
By default, every
dependent must have a
principal, but
EF Core does not enforce
this
Ooh! We should publish a book on all the
funny things our pets do!
Now we’ll have to find an author.
Allowing Optional Parent
public class Book t Specify the FK property is nullable
{ ...
public int? AuthorId { get; set; }
}

modelBuilder.Entity<Author>() t Map the FK property as not required


.HasMany(a => a.Books)
.WithOne(b => b.Author)
.HasForeignKey(b => b.AuthorId)
.IsRequired(false);

modelBuilder.Entity<Author>() t When FK property doesn’t exist, map the


.HasMany(a => a.Books) inferred (“shadow”) property as not required
.WithOne(b => b.Author)
.HasForeignKey("AuthorId")
.IsRequired(false);
Many ways to describe one-to-many that
conventions will recognize

Summary You can add mappings if those patterns


don’t align with your desired logic
Foreign keys are your friends
An unconventional FK name is a common
“gotcha” which you can fix in mappings
Watch out for required principals!
Use the EF Core Power Tools to verify how
EF Core will interpret the data model
Up Next:

Logging EF Core Activity and SQL


Resources

Entity Framework Core on GitHub: github.com/dotnet/efcore

EF Core Documentation: docs.microsoft.com/ef/core

EF Core Power Tools Extension (model visualizer, scaffold and more):


https://github.com/ErikEJ/EFCorePowerTools

You might also like