Home > Mobile >  Configuring a read only navigation property as a constructor parameter
Configuring a read only navigation property as a constructor parameter

Time:10-01

I have the following models:

public class Session
{
    public string Id { get; set; }

    public IList<SessionWorkspace> Workspaces { get; } = new List<SessionWorkspace>();
}
public class SessionMeasurement
{
    public SessionMeasurement(Session session, string measurement)
    {
        Session = session;
        Measurement = measurement;
    }

    public string Id { get; set; }

    public Session Session { get; }
    public string Measurement { get; }
}

But I am struggling to configure them without getting an error. When I do this:

modelBuilder
    .Entity<Session>(entityBuilder =>
    {
        entityBuilder
            .HasMany(s => s.Workspaces)
            .WithOne(sw => sw.Session);
    });

modelBuilder.Entity<SessionWorkspace>(entityBuilder =>
{
    entityBuilder
        .Property(sw => sw.Session);
    entityBuilder
        .Property(sw => sw.Workspace);
});

I get the error:

System.InvalidOperationException: ''Session' cannot be used as a property on entity type 'SessionWorkspace' because it is configured as a navigation.'

But when I don't configure Session as a property like this:

modelBuilder
    .Entity<Session>(entityBuilder =>
    {
        entityBuilder
            .HasMany(s => s.Workspaces)
            .WithOne(sw => sw.Session);
    });

modelBuilder.Entity<SessionWorkspace>(entityBuilder =>
{
    entityBuilder
        .Property(sw => sw.Workspace);
});

I get this error:

System.InvalidOperationException: 'No suitable constructor was found for entity type 'SessionWorkspace'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'session' in 'SessionWorkspace(Session session, string workspace)'.'

So do I properly configure a readonly navigation property that is passed through the constructor?

CodePudding user response:

Navigation properties are not "properties" by EF Core terminology, but "navigations". Hence you cannot use methods called Property to configure/access them. EF Core 5.0 provides special method called Navigation for fluently configuring them, which however won't solve the original problem.

And the original problem is that navigation properties are not supported in constructors

  • EF Core cannot set navigation properties (such as Blog or Posts above) using a constructor.

So, remove the Property fluent call and just add a private parameterless constructor to your class to be used by EF Core when materializing it. e.g.


// for EFC
private SessionMeasurement() { }

// for public
public SessionMeasurement(Session session, string measurement)
{
    Session = session;
    Measurement = measurement;
}

  • Related