Gareth Lewis
Gareth Lewis

Reputation: 751

Entity Framework 5 Code First Relationships

I'm having trouble understanding how to create relationships between classes on a project that I'm building.

I have a class Photo that has a required one-to-one relationship with PhotoExif, and Photo has an optional one-to-one relationship with FeaturedPhoto.

I'm getting the error:

Unable to determine composite primary key ordering for type Website.Models.PhotoExif. Use the ColumnAttribute or the HasKey method to specify an order for composite primary keys.

Help would be much appreciated.

Photo.cs

public class Photo
{
    [Key]
    public int PhotoID { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }
    public Orientation Orientation { get; set; }
    public int Rating { get; set; }
    public string URL { get; set; }
    public string Filename { get; set; }
    public DateTime DateAdded { get; set; }
    public bool Hide { get; set; }
    public string MetaDescription { get; set; }
    public string MetaKeywords { get; set; }

    public virtual PhotoExif PhotoExif { get; set; }
} 

PhotoExif.cs

public class PhotoExif
{
    [Key]
    public int PhotoExifID { get; set; }

    public int PhotoID { get; set; }

    public string ShutterSpeed { get; set; }
    public string Aperture { get; set; }
    public string FocalLength { get; set; }
    public int ISO { get; set; }
    public string ExposureBias { get; set; }
    public bool Flash { get; set; }
    public string WhiteBalance { get; set; }
    public string Lens { get; set; }
    public DateTime DateTaken { get; set; }
    public float Longitude { get; set; }
    public float Latitude { get; set; }
    public int Zoom { get; set; }
    public string Location { get; set; }

    public virtual Photo Photo { get; set; }
}

FeaturedPhoto.cs

public class FeaturedPhoto
{
    [Key]
    public int FeaturedPhotoID { get; set; }

    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string InformationLocation { get; set; }
    public string ImagePosition { get; set; }

    public virtual Photo Photo { get; set; }
}

Upvotes: 1

Views: 1936

Answers (2)

mclaassen
mclaassen

Reputation: 5138

As per the error message:

Use the ColumnAttribute or the HasKey method to specify an order for composite primary keys.

you need to add [Column(Order="#")] annotations to PhotoID and PhotoExifID properties of the PhotoExif table.

Upvotes: 1

Slauma
Slauma

Reputation: 177163

To me it looks that you don't want a composite primary key on PhotoExif. I don't know why EF tries to infer a composite key, but the reason is possibly 1) that the Photo property has the PhotoID property as foreign key by convention, 2) in a one-to-one relationship the foreign key must be identical with the primary key, 3) there is another property PhotoExifID you have marked a key. So, maybe, EF assumes that this marked key plus the infered key from the one-to-one relationship form a composite key together. (This behaviour would be pretty strange, but I can't see how your model and your annotations could lead to this exception about composite key ordering.)

Anyway, the PhotoID property doesn't seem right, because in a one-to-one relationship principal and dependent must share the same primary key and the FK of the dependent is the PK at the same time. I would try to remove this property and add a FK attribute:

public class PhotoExif
{
    [Key]
    public int PhotoExifID { get; set; }

    public string ShutterSpeed { get; set; }
    //...

    [ForeignKey("PhotoExifID")]
    public virtual Photo Photo { get; set; }
}

Similarly you must define the FK for FeaturedPhoto, otherwise EF cannot determine what's the principal and what's the dependent of the relationship. Depending on the details of the relationships - are they required-required, required-optional or optional-optional and which entity is principal and which one is dependent? - it might be necessary to define the mapping with Fluent API since data annotations do not support every mapping option that Fluent API does.

Upvotes: 0

Related Questions