Working with Relationships between Entities

Description and code samples
Table of Contents
Description

Overview

The domain model exposes relationships using navigation properties and, optionally, a foreign key property. Therefore a relationship can be represented by up to three properties:

  • Two navigation properties; and
  • A foreign key property, in case of Foreign Key Association
Changing a relationship is achieved by changing the values assigned to one of these properties of either end of the relationship.

Entity Framework will take care of updating the rest of the relationship  properties. This process is known as relationship fix-up and happens when:

  • The method DbContext.SaveChanges() is called; OR
  • The DbContext.DetectChanges() is called explicitly.
Operations
Adding a relationship between two entity objects (one-to-one relations)

To add a new relationship, one of the objects in the relationship has to be assigned to the reference navigation property of the other object.

How to do it
using (var context = new BreakAwayContext())
  {
    var resort = new Resort
    {
      Name = "Pete's Luxury Resort"
    };

    context.Lodgings.Add(resort);

    var canyon = (from d in context.Destinations
                  where d.Name == "Grand Canyon"
                  select d).Single();

    canyon.Lodgings.Add(resort);

    context.SaveChanges();
  }
Adding a relationship between two entity objects (one-to-many relations)

To add a new relationship, one of the objects in the relationship has to be assigned to the collection navigation property of the other object using the DbSet.Add() method.

Remarks

Since the navigation property of either end of the relationship can be updated, instead of adding the new entity object to the collection of the entity objects, the navigation property of the entity that represents the “many” side can be set/assigned to the entity object that represents the “one” side.

If the entity object that represents the “many” side exposes a foreign key property then it could be assigned to the primary key of the object entity that represents the one” side.

How to do it

Option 1: Using navigation properties (one-to-many direction)

using (var context = new BreakAwayContext())
  {
    var resort = new Resort
    {
      Name = "Pete's Luxury Resort"
    };

    context.Lodgings.Add(resort);

    var canyon = (from d in context.Destinations
                  where d.Name == "Grand Canyon"
                  select d).Single();

    canyon.Lodgings.Add(resort);

    context.SaveChanges();
  }

Option 2: Using navigation properties (many-to-one direction)

...
resort.Destination = canyon;
...

Option 3: Using foreign key prooperties

...
resort.DestinationId = canyon.DestinationId;
...
Changing a relationship between two entity objects (one-to-one and one-to-many relations)

Changing a relationship is the same as adding a new relationship.

To change a relationship:

1) Locate and load the entity to be changed;
2) Locate and load the new entity to replace in the relationship;
3) Update the navigation property or foreign key property.

This will result in a single UPDATE statement being sent to the database to update the FK column.

Remarks

There is no need to remove the existing relationship.

How to do it

Option1: Updating navigation properties:

  using (var context = new BreakAwayContext())
  {
    var hotel = (from l in context.Lodgings
                     where l.Name == "Grand Hotel"
                     select l).Single();

    var reef = (from d in context.Destinations
                  where d.Name == "Great Barrier Reef"
                  select d).Single();

    hotel.Destination = reef;

    context.SaveChanges();
  }

Option2: Updating foreign key property:

...
hotel.DestinationId = reef.DestinationId;
...

Generated SQL:

exec sp_executesql N'update [dbo].[Lodgings]
set [destination_id] = @0
where ([LodgingId] = @1)
',N'@0 int,@1 int',@0=4,@1=1
Removing a relationship between two entity objects (one-to-one and one-to-many optional relations)

To remove a relationship:

1) Locate and load the target entity object to remove;
2) Locate and load the related entity object with the collection navigation property (in case of a one-to-many relationship);
3) Remove the target entity object obtained on (1) from the navigation collection property of the object obtained on (2) (in case of a one-to-many relationship)

OR

3) Set the navigation property or foreign key property to NULL on the target object entity

This will result in a single UPDATE statement being sent to the database to update the FK column as NULL.

Remarks

The target object entity must be loaded in order to register it on the context, change the navigation property or foreign key property , and have that change registered in the change tracker.

How to do it

Option 1: Removing entity relationship using navigation property

using (var context = new BreakAwayContext())
  {
    var davesDump = (from l in context.Lodgings
                     where l.Name == "Dave's Dump"
                     select l).Single();

    context.Entry(davesDump)
      .Reference(l => l.PrimaryContact)
      .Load();

    davesDump.PrimaryContact = null;

    context.SaveChanges();
  }

Option 2: Removing entity relationship using foreign key property:

 using (var context = new BreakAwayContext())
  {
    var davesDump = (from l in context.Lodgings
                      where l.Name == "Dave's Dump"
                      select l).Single();

    davesDump.PrimaryContactId = null;

    context.SaveChanges();
  }