Matthew Flynn
Matthew Flynn

Reputation: 3941

Composite Key and using Multiple Column Attributes in Entity Framework 6

I am trying to create a composite key using two fields when using code first to existing fields in a table in a db;

    [Key,Column("driverId", Order=0)]
    [JsonProperty(PropertyName="driverid")]
    public override int ID { get; set; }

    [Key,Column("type", Order=1)]
    [JsonProperty(PropertyName="typeid")]
    public int Type { get; set; }

Now when I try to run a new migration i get the following error;

The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical. DriversToVehicle_Driver_Target_DriversToVehicle_Driver_Source: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.

The DriversToVehicle table is as follows;

public partial class DriversToVehicle
{
    [Column("id"), Key]
    public int ID { get; set; }

    [Column("driverid")]
    public int DriverID { get; set; }
    [ForeignKey("DriverID")]
    public Driver Driver { get; set; }

    [Column("vehicleid")]
    public int VehicleID { get; set; }
    [ForeignKey("VehicleID")]
    public Vehicle Vehicle { get; set; }
}

Extending this question, originally a single key on the ID, i.e.

    [Column("driverId")]
    [JsonProperty(PropertyName="driverid")]
    public override int ID { get; set; }

Now moving forward, how will this effect the other entities linking to it (by this i mean code first in the classes)? will ef automatically sort this out? or do I now need to have both keys in other entities when linking to this class?

e.g. as before I would have had

public virtual Driver myDriver;

Obviously now instead of linking on the ID alone it needs to be linked with the Type as well.

Thanks in advance.

EDIT FOR ANSWER

Ok, I extracted the Type out to a seperate class. The main issue is now How do i mark the foreign key as also being a composite key?

I have the following classes

    public partial class DriverType 
    {
        [Column("Id")]
        [JsonProperty(PropertyName = "drivertypeid")]
        public override int ID { get; set; }

        [JsonProperty(PropertyName = "drivertype")]
        public string Name { get; set; }
    }

Then in the Driver I have the following (reduced for brevity);

public partial class Driver : AuditableEntity<int>
{
    [Key,Column("driverId", Order=0)]
    [JsonProperty(PropertyName="driverid")]
    public override int ID { get; set; }

    [Key,Column("type", Order=1)]
    [ForeignKey("DriverType")]
    [JsonProperty(PropertyName="drivertypeid")]
    public int DriverTypeId { get; set; }
    public DriverType DriverType { get; set; }

How do I then add it to the DriverToVehicle class please? So far I have

public partial class DriversToVehicle { [Column("id"), Key] public int ID { get; set; }

    [Column("driverid", Order=0), ForeignKey("Driver")]
    public int DriverID { get; set; }
    public Driver Driver { get; set; }

    [Column("type", Order = 1), ForeignKey("Driver")] 
    public int DriverTypeId { get; set; }

    [ForeignKey("DriverTypeId")]
    public DriverType DriverType { get; set; }

}

This doesnt look right to me though?

Upvotes: 0

Views: 2055

Answers (1)

Rich Turner
Rich Turner

Reputation: 11014

Since your Drivers table's Primary Key is now (DriverId, Type), you can no longer reference your drivers by DriverId alone - you must reference them by both DriverId and Type. Therefore, your DriversToVehicle table needs to look something like this:

public partial class DriversToVehicle
{
    [Column("id"), Key]
    public int ID { get; set; }

    [Column("driverid")]
    public int DriverID { get; set; }
    [ForeignKey("DriverID")]
    public Driver Driver { get; set; }

    [Column("DriverType")]
    public int DriverType { get; set; }
    [ForeignKey("type")]
    public int DriverType { get; set; }

    [Column("vehicleid")]
    public int VehicleID { get; set; }
    [ForeignKey("VehicleID")]
    public Vehicle Vehicle { get; set; }
}

However, as @hopeless states above, you may not need to model this join table if you correctly model your Driver and Vehicle types correctly.

HTH.

Upvotes: 0

Related Questions