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

interacting-with-related-data-slides

Uploaded by

ahmed11611612
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views

interacting-with-related-data-slides

Uploaded by

ahmed11611612
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 70

Interacting with Related

Data

Julie Lerman
EF Core Expert and Software Coach

@julielerman | thedatafarm.com
Focus on the one-to-many authors & books
Module
Inserting related data
Overview
Eager loading queries and shaping results
with projections
Loading related data for objects in memory
Filtering queries with related data
Update and delete related data
Insights into persisting untracked graphs
Bette Davis in “All About Eve”

"Fasten your seat belts, it's


gonna be a bumpy night."
Bette Davis in “All About Eve”

"Fasten your seat belts, it's


gonna be a bumpy night."
ing modu le
in te r e st
an
Adding Related Data
+
Add New Parent and New Child
Together
Let’s add new authors and their new books
One-to-Many in the Database

The relationship Constraints of this relationship

Views from SQL Server Management Studio


Object Graph
A connected set of related objects
Any Object Can Be the Head of a Graph

Author Graph Book Graph


An author with some A book with an author and
books in memory its book jacket in memory
+
Add a New Child to an Existing Parent
Our authors keep writing new books.
Let’s get those books into the database
Change Tracker Response
to New Child of Existing Parent

As child’s key value is Child’s FK value to parent


not set, state will (e.g. Book.AuthorId)
automatically be “Added” is set to parent’s key
Reminder: DbContext/DbSet Tracking Methods

Add Update Remove Attach


Change Tracker Response
to New Child of Existing Parent

Set foreign key


Add child to child Add existing
property in child
collection of tracked parent to
class to parent’s
existing tracked ref property of
key value.
parent. child.
Add &
SaveChanges SaveChanges
SaveChanges
Beware accidental
inserts!
Passing a pre-existing entity into its
DbSet Add will cause EF Core to try to
insert it into the database!
EF Core’s Default Entity State of Graph Data

Has Key Value No Key Value

Add(graph) Added Added

Update(graph)

Attach(graph)
EF Core’s Default Entity State of Graph Data

Has Key Value No Key Value

Add(graph) Added* Added

Update(graph) *Database will throw an exception


unless IDENTITY INSERT is explicitly
enabled and the key doesn’t already
exist
Attach(graph)
Understand
how your tools work!
“Foreign keys? NEVER!
They will make my classes dirty!”

“Foreign keys in my classes


make my life so much simpler!”
Some of this change
tracking behavior is
different in disconnected
scenarios.
Eager Loading Related Data in Queries
Means to Get Related Data from the Database

Query Projections
Eager Loading
Define the shape of query
Include related objects in query
results

Lazy Loading Explicit Loading


Explicitly request related data
On-the-fly retrieval of data for
related to objects in memory objects in memory
*Arrived with EF Core 2.1
Query Workflow

Receives Materializes
tabular results results as objects
Authors Books for
those Adds tracking
Authors details to
DbContext
instance
DbContext
connects the
relationships
Filtering & Sorting the Included Data

Long requested
By default, the You can filter and
feature that finally
entire collection is sort the related
arrived in
retrieved data
EF Core 5!
Composing Include with Other LINQ Methods

_context.Authors.Where(a=>a.LastName.StartsWith("L"))
.Include(a=>a.Books).ToList()

_context.Authors.Where(a => a.LastName == "Lerman")


.Include(a => a.Books).FirstOrDefault()

_context.Authors.Where(a => a.LastName == "Lerman")


.FirstOrDefault().Include(a => a.Books)

_context.Authors.Find(1).Include(a=>a.Books)
_context.Authors.Include(a=>a.Books).Find(1)
Remember, Find is not a LINQ method
Using Include for Multiple Layers of Relationships
_context.Authors
.Include(a => a.Books) t Get books for each author
.ThenInclude(b=>b.BookJackets) t Then get the jackets for each book
.ToList();

_context.Authors
t Get books for each author
.Include(a => a.Books)
.Include(a=>a.ContactInfo) t Also get the contact info each author
.ToList();

t Get the jackets for each author’s books


_context.Authors
.Include(a=>a.Books.BookJackets) (But don’t get the books)
.ToList();
Performance Considerations with Include

Composing many Includes in one Include defaults to a single SQL


query could create performance command. Use AsSplitQuery() to
issues. Monitor your queries! send multiple SQL commands
instead.
SQL Generated from Includes

Query is broken up
Single query
into multiple queries sent
with LEFT JOIN(s)
in a single command

Default With AsSplitQuery()


Projecting Related Data in Queries
Means to Get Related Data from the Database

Query Projections
Eager Loading
Define the shape of query
Include related objects in query
results

Lazy Loading Explicit Loading


Explicitly request related data
On-the-fly retrieval of data for
related to objects in memory objects in memory
var someType=_context.Authors
.Select(properties into a new type)
.ToList()

var someType=_context.Authors
.Select(a=>new {a.FirstName, a.LastName, a.Books.Count() }
.ToList()

someType structure:
FirstName
LastName
Books

Projecting into Undefined (“Anonymous”) Types


Use LINQ’s Select method
Use a lambda expression to specify properties to retrieve
Instantiate a type to capture the resulting structure
Anonymous types are not available outside of the method
EF Core Can Only Track Entities Known by DbContext

Anonymous types Entities that are properties


of an anonymous type
are not tracked are tracked
Loading Related Data for Objects
Already in Memory
Means to Get Related Data from the Database

Query Projections
Eager Loading
Define the shape of query
Include related objects in query
results

Loading related data for objects already in memory


Means to Get Related Data from the Database

Query Projections
Eager Loading
Define the shape of query
Include related objects in query
results

Explicit Loading
Lazy Loading
Explicitly request related data
On-the-fly retrieval of data
for related to objects in memory
objects in memory
With author object already in memory, load a collection

_context.Entry(author).Collection(a => a.Books).Load();

With book object already in memory, load a reference (e.g., parent or 1:1)

_context.Entry(book).Reference(b => b.Author).Load();

Explicit Loading
Explicitly retrieve related data for objects already in memory
DbContext.Entry(object).Collection().Load()
DbContext.Entry(object).Reference().Load()
More on Explicit Loading

You can only load from a single object Profile to determine if LINQ query
would be better performance

Filter on loading using Query() method var newfBooks =


context.Entry(author)
.Collection(a => a.Books)
.Query().Where(b =>
b.Title.Contains(“Newf”)
.ToList();
Using Lazy Loading to Retrieve Related
Data
Means to Get Related Data from the Database

Query Projections
Eager Loading
Define the shape of query
Include related objects in query
results

Explicit Loading Lazy Loading


Explicitly request related data for On-the-fly retrieval of data
objects in memory related to objects in memory
Lazy loading is easy to misuse!
I recommend some advanced learning before
using it.
Lazy Loading is OFF by default
Enabling Lazy Loading

Every navigation property in every entity must be virtual


e.g., public virtual List<Book> Books { get; set; }

Reference the Microsoft.EntityFramework.Proxies package

Use the proxy logic provided by that package


optionsBuilder.UseLazyLoadingProxies()
Some Good and Not So Good Ways to Use Lazy
Loading
Good Behavior
foreach(var b in author.Books) t One command to the db to get the books for
this one author
{
Console.WriteLine(b.Title);
}

Behavior to Avoid
var bookCount= author.Books.Count(); t Retrieves all the Book objects from the
database and materialize them and then give you
the count.
t Sends N+1 commands to the database as each
Data bind a grid to lazy-loaded data author’s book is loaded into a grid row

Lazy loading when no context in scope t No data is retrieved


Using Related Data to Filter Objects
Modifying Related Data
EF Core’s Default Entity State of Graph Data

Has Key Value No Key Value

Add(graph) Added Added

Update(graph) Modified Added

Attach(graph)
Connected Disconnected

DbContext is aware DbContext has no clue


of all changes made to objects about history of objects
that it is tracking before they are attached
(when DetectChanges is called)
Reminder: DbContext/DbSet Tracking Methods

Add Update Remove Attach

Attach starts tracking with state set to Unchanged


EF Core’s Default Entity State of Graph Data

Has Key Value No Key Value

Add(graph) Added Added

Update(graph) Modified Added

Attach(graph) Unchanged Added


The Challenge

Edited
Book
Author

Book Book
The Challenge

Edited
Book

Author

Book Book
The Challenge

_context.Entry
( Edited
Book
)
.State

Author

Book Book
The Challenge

_context.Entry
( Edited
Book
)
.State

Author

Book Book
DbContext.Entry gives you
a lot of fine-grained control
over the change tracker.
Understanding Deleting Within Graphs
Multiple Meanings of Remove/Delete

Remove from an Set State to Deleted Delete from database


in-memory collection in Change Tracker
Cascade Delete When Dependents
Can’t Be “Orphaned”
When parent is optional, the
children will not be deleted
When parent is optional, the
children will not be deleted

This was a breaking change in EF Core 7


I will start with a focus on
required parents and
cascade delete enabled.
Foreign Key Relationship Constraint in SQL Server
void DeleteAnAuthor()
{
var author = _context.Authors.Find(2);
_context.Authors.Remove(author);
_context.SaveChanges();
}

Database Enforces Cascade Delete


Only author is in memory, tracked by EF Core & marked “Deleted”
Database’s cascade delete will take care of books when author is deleted
EF Core Enforces
Cascade Deletes
Any related data that is also tracked
will be marked as Deleted along with
the principal object
It’s running the
DELETE FROM Books
while the books are still in
the database.
var author=_context.Authors t Retrieve an author with only *some* of their
.Include(a=>a.Books books
.Where(b=>b.Title=“XYZ”)
.FirstOrDefault();

t Mark the author as deleted


_context.Authors.Remove(author);

//Entry(author).State=Deleted t Change tracker will also mark that book as


//Entry(thatbook).State=Deleted deleted

DELETE thatbook FROM BOOKS t SaveChanges sends DELETE for that book and
DELETE for the author to database
DELETE thatauthor FROM AUTHORS

//database cascade delete any other t The database will delete any remaining books
books in that database for the author
A Few Last Questions about Cascade Delete

Question Answer
Will Remove() remove everything in a No. Remove will only remove the
graph, just like Update? specific object.

What about deleting a dependent that’s You’ve actually done this. If it’s in
not in a graph? memory, DbSet.Remove works. If it’s
not, then ExecuteDelete.
Some More Points About Removing Dependents

What about .... Examples


How to move a child from one parent to • book.AuthorId=3
another (when tracked)? • newAuthor.Books.Add(book)
• book.Author=newAuthor

What about optional relationships? • book.AuthorId=null


• author.Books.Remove(book)

What about deleting relationships in This is more advanced, but you will see
disconnected scenarios? some of it in the web app module.
Impact of Optional Relationship

No Cascade Delete in the Database No Cascade Delete in


ChangeTracker
You can eager load related data with
Include() or projections.
Lazy and explicit loading let you load after
Review the fact.
Pay attention to lazy loading behavior.
Filter the related data or use it to filter the
base data.
Adding, modifying or deleting data in
graphs has varying impacts on the related
objects.
DbContext.Entry() isolates and affects only
the object you pass in.
Up Next:

Defining and Using Many-to-Many


Relationships
Resources

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

EF Core Documentation learn.microsoft.com/ef/core

Lazy Loading With and Without Proxies


(Module from EF Core 2.1 What’s New) bit.ly/EFCoreLazy

You might also like