Michael K
Michael K

Reputation: 832

EF optional one to many multiplicity error

I have a very simple schema, simplified further for this question

Table: Airport
IATA char(3) Primary Key
Name varchar(20)

Table: Airport_Terminal
IATA char(3) (comp key1)
TerminalName (comp key2)

POCOs
public sealed class Airport
{
    [Key]
    public string IATA { get; set; }       

    public string Name { get; set; }

    public ICollection<AirportTerminal> Terminals { get; set; }
}

    public class AirportTerminal
{
    [Key, Column(Order = 0)]
    public string IATA { get; set; }

    [Key, Column(Order = 1)]
    public string Terminal { get; set; }

    public Airport Airport { get; set; }

}

AirportTerminal Configuration

modelBuilder.Entity<AirportTerminal>()
    .HasOptional<Airport>(s => s.Airport)
    .WithMany(s => s.Terminals)
    .HasForeignKey(s => s.IATA);

Some airports (in my application) have multiple terminals and some do not. I simply want to react to Terminals property when there are Terminals defined for a given airport. If I enter a single record for every airport, this configuration works. But when I attempt to lookup any airport, I get:

 "One or more validation errors were detected during model generation: Multiplicity conflicts with the referential constraint in Role 'AirportTerminal_Airport_Target' in relationship 'AirportTerminal_Airport'. Because all of the properties in the Dependent Role are non-nullable, multiplicity of the Principal Role must be '1'."

Research shows that this error occurs when a non-nullable property exists on the optional member, so it cannot be set to null. AirportTerminal contains two strings, nullable.

Any ideas?

Upvotes: 0

Views: 102

Answers (1)

Jones
Jones

Reputation: 1500

Consider using only key to the tables. This is best instead of multiple key. Place index constraint to ensure uniqueness in the properties IATA and Terminal.

POCOs:

public sealed class Airport
{
    [Key]
    public Guid Id { get; set; }

    public string IATA { get; set; }       

    public string Name { get; set; }

    public ICollection<AirportTerminal> Terminals { get; set; }
}

public class AirportTerminal
{
    [Key]
    public Guid Id { get; set; }

    public string IATA { get; set; }

    public string Terminal { get; set; }

    public Airport Airport { get; set; }

    public Guid? AirportId { get; set; }
}

Configuration:

modelBuilder.Entity<AirportTerminal>()
    .HasOptional<Airport>(s => s.Airport)
    .WithMany(s => s.Terminals)
    .HasForeignKey(s => s.AirportId);

Upvotes: 1

Related Questions