Keith Barrows
Keith Barrows

Reputation: 25308

Entity Framework Code 1st - Mapping many-to-many with extra info

I've looked through several of the questions here and am not quite connecting all the (mental) dots on this. I would appreciate some help.

My Models (code first):

public class cgArmorial
{
    [Key]
    [Display(Name = "Armorial ID")]
    public Guid ArmorialID { get; set; }
    [Display(Name = "User ID")]
    public Guid UserId { get; set; }
    public string Name { get; set; }
    public string DeviceUrl { get; set; }
    public string Blazon { get; set; }

    public virtual ICollection<cgArmorialAward> ArmorialAwards { get; set; }
}

public class cgArmorialAward
{
    public cgArmorial Armorial { get; set; }
    public cgAward Award { get; set; }
    public DateTime AwardedOn { get; set; }
}
public class cgAward
{
    [Key]
    [Display(Name = "Award ID")]
    public Guid AwardID { get; set; }
    public string Name { get; set; }
    public string Group { get; set; }
    public string Description { get; set; }
    public string ImageUrl { get; set; }
    public string Blazon { get; set; }

    public virtual ICollection<cgArmorialAward> ArmorialAwards { get; set; }
}

Then in my Context class I have (last 2 entries):

public class Context : DbContext
{
    public DbSet<cgUser> Users { get; set; }
    public DbSet<cgEvent> Events { get; set; }
    public DbSet<cgEventType> EventTypes { get; set; }
    public DbSet<cgArmorial> Armorials { get; set; }
    public DbSet<cgAward> Awards { get; set; }
    public DbSet<cgArmorialAward> ArmorialAwards { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<cgUser>()
                    .HasMany<cgEvent>(e => e.EventAutocrats)
                    .WithMany(u => u.EventAutocrats)
                    .Map(m =>
                    {
                        m.ToTable("EventAutocrats");
                        m.MapLeftKey("UserId");
                        m.MapRightKey("EventId");
                    });
        modelBuilder.Entity<cgUser>()
                    .HasMany<cgEvent>(e => e.EventStaff)
                    .WithMany(u => u.EventStaff)
                    .Map(m =>
                    {
                        m.ToTable("EventStaff");
                        m.MapLeftKey("UserId");
                        m.MapRightKey("EventId");
                    });
        modelBuilder.Entity<cgArmorialAward>()
                    .HasRequired(a => a.Armorial)
                    .WithMany(b => b.ArmorialAwards);
        modelBuilder.Entity<cgArmorialAward>()
                    .HasRequired(a => a.Award)
                    .WithMany();    // b => b.ArmorialAwards
    }
}

I am getting this error when I try to run:

System.Data.Edm.EdmEntityType: : EntityType 'cgArmorialAward' has no key defined. Define the key for this EntityType. System.Data.Edm.EdmEntitySet: EntityType: EntitySet �ArmorialAwards� is based on type �cgArmorialAward� that has no keys defined.

Upvotes: 1

Views: 1366

Answers (1)

Slauma
Slauma

Reputation: 177163

Well, as the exception says: You don't have a key defined on your entity cgArmorialAward. Every entity must have a key. Change it to the following:

public class cgArmorialAward
{
    [Key, Column(Order = 0)]
    [ForeignKey("Armorial")]
    public Guid ArmorialID { get; set; }

    [Key, Column(Order = 1)]
    [ForeignKey("Award")]
    public Guid AwardID { get; set; }

    public cgArmorial Armorial { get; set; }
    public cgAward Award { get; set; }
    public DateTime AwardedOn { get; set; }
}

The fields in the composite key are foreign keys to the other two tables at the same time, hence the ForeignKey attribute. (I'm not sure if conventions would detect this automatically because you have non-standard names ("cgXXX" for the classes and "XXXId" for the foreign key properties). On the other hand the property names Armorial and Award match the foreign key property names. I'm not sure if EF conventions would consider this. So, perhaps the ForeignKey attribute is not necessary but at least it's not wrong.)

Upvotes: 4

Related Questions