How to access chained/nested property in EF Core 2.2

1.2k views Asked by At

I have the following classes:

public class Vehicle{
    public Engine TurboV6 { get; set; }

public class Engine{
    public Cylinder Core { get; set; }

public class Cylinder{
    public double? Capacity { get; set; }

And I have configured the owned entities as below in OnModelCreating method:

    modelBuilder.Entity<Vehicle>()
                .OwnsOne(
                    v => v.TurboV6, e=> {
                        e.OwnsOne(e => e.Core);
                    });

The Problem

When I tried to save a null value in the owned entity like v.TurboV6.Core = null; EF Core does not save null value in the Vehicle.TurboV6.Core.Capacity as null, instead the previous value persists in the database. I assume this is caused by a problem in EF Core's change tracking.

I tried to overcome this with :

vContext = DbContext.Vehicles.Add(new Vehicle());
vContext.Property(v => v.TurboV6.Core.Capacity).IsModified = true;

Take note that vContext is EntityEntry<Vehicle> type, not DbContext.

Similar to this question: Nested navigation properties using entity entry reference ,

When I access the code below:

vContext.Property(v => v.TurboV6.Core.Capacity).IsModified = true;

I got an error message saying

System.ArgumentException : The expression 'v => v.TurboV6.Core.Capacity' is not a valid property expression. The expression should represent a simple property access: 't => t.MyProperty'. (Parameter 'propertyAccessExpression')

I am using EF Core 2.2.6

Is it possible to map chained property like above? Have I missed anything? If yes, how do I do so?

Thank you

1

There are 1 answers

5
Ivan Stoev On

TurboV6 and Core are reference navigation properties, so they must be accessed through Reference method. The nested entity entry is accessible through TargetEntry property. Repeat that until you get to the desired level entry on which you can use Property method.

Something like this:

vContext
    .Reference(e => e.TurboV6).TargetEntry
    .Reference(e => e.Core).TargetEntry
    .Property(e => e.Capacity).IsModified = true;