xeraphim
xeraphim

Reputation: 4645

Entity Framework 6: Composite Key in 1:n relationship

I have the following tables:

Person (string socialNumber, string name)

Snapshot (int snapshotId, DateTime date

InfoOverTime (int snapshotId, string socialNumber, string desc, ...)

The bold columns should be primary keys with snapshotId and socialNumber of InfoOverTime also being foreign keys.

I tried to create this configuration in code first like this:

public class Person
{
    public Person()
    {
    }

    [Key]
    public string SocialNumber { get; set; }
    public string Name { get; set; }

    public InfoOverTime InfoOverTime { get; set; }
}

public class Snapshot
{
    public Snapshot()
    {
    }

    public int SnapshotId { get; set; }
    public DateTime Date { get; set; }
}

public class InfoOverTime
{
    public InfoOverTime()
    {
    }

    [Key, Column(Order = 0), ForeignKey("Snapshot")]
    public int SnapshotId { get; set; }
    public Snapshot Snapshot { get; set; }

    [Key, Column(Order = 1), ForeignKey("Person")]
    public string PersonId { get; set; }
    public Person Person{ get; set; }

    public string Desc { get; set; }
    ...
}

Unfortunately, I get the following error message:

An unhandled exception of type 'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll

Additional information: One or more validation errors were detected during model generation:

InfoOverTime_Person_Source: : Multiplicity is not valid in Role 'InfoOverTime_Person_Source' in relationship 'InfoOverTime_Person'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

I also tried to do it via EntityTypeConfiguration like this:

public class InfoOverTimeMap : EntityTypeConfiguration<InfoOverTime>
{
    public InfoOverTimeMap()
    {
        this.HasKey(pc => new {pc.SnapshotId, pc.PersonId});
        this.HasRequired(x => x.Snapshot).WithMany().HasForeignKey(x => x.SnapshotId);
        this.HasRequired(x => x.Person).WithMany().HasForeignKey(x => x.PersonId);
    }
}

But this doesn't work either :-(

What am I doing wrong?

Thanks in advance

Upvotes: 1

Views: 596

Answers (3)

Engineert
Engineert

Reputation: 192

You need to remove public InfoOverTime InfoOverTime { get; set; }. Besides, if you use virtual keyword with Person and Snapshot in InfoOverTime, EF can map related Person and Snapshot.

Codes should look like:

 public class Person
 {
    public Person()
    {
    }

    [Key]
    public string SocialNumber { get; set; }
    public string Name { get; set; }

 }

 public class Snapshot
 {
     public Snapshot()
     {
     }

    public int SnapshotId { get; set; }
    public DateTime Date { get; set; }
}

 public class InfoOverTime
 {
    public InfoOverTime()
    {
    }

    [Key, Column(Order = 0), ForeignKey("Snapshot")]
    public int SnapshotId { get; set; }
    public virtual Snapshot Snapshot { get; set; }

    [Key, Column(Order = 1), ForeignKey("Person")]
    public string PersonId { get; set; }
    public virtual Person Person{ get; set; }

    public string Desc { get; set; }

}

Upvotes: 0

Tanveer Ali
Tanveer Ali

Reputation: 166

you missed the following in Snapshot class:

public virtual InfoOverTime InfoOverTime { get; set; }

Upvotes: 0

Kyle Huang
Kyle Huang

Reputation: 451

In addition to others' comment and answer, you might also have missed the "Key" attribute for Snapshot

[Key]
public int SnapshotId { get; set; }

Upvotes: 0

Related Questions