Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I map a composite primary key in Entity Framework 4 code first?

I'm getting to grips with EF4 code first, and liking it so far. But I'm having trouble mapping an entity to a table with a composite primary key.

The configuration I've tried looks like this:

public SubscriptionUserConfiguration()      {                 Property(u => u.SubscriptionID).IsIdentity();                 Property(u => u.UserName).IsIdentity();     } 

Which throws this exception: Unable to infer a key for entity type 'SubscriptionUser'.

What am I missing?

like image 268
jamesfm Avatar asked Apr 28 '10 21:04

jamesfm


People also ask

How do you get a composite key in code first?

In order to use composite keys, Entity Framework requires you to define an order for the key properties. You can do this by using the Column annotation to specify an order. The order value is relative (rather than index based) so any values can be used. For example, 100 and 200 would be acceptable in place of 1 and 2.

How do I create a composite primary key in Entity Framework Core?

Entity Framework Core supports composite keys - primary key values generated from two or more fields in the database. Composite keys are not covered by conventions or data annotation attributes. The only way to configure composite keys is to use the HasKey method.


2 Answers

You could also use

HasKey(u => new { u.SubscriptionID, u.UserName }); 

Edit:

One limitation I have found is that the following do not work:

public ProjectAssignmentConfiguration() {     HasKey(u => u.Employee.EmployeeId);     HasKey(u => u.Project.ProjectId); } 

or

public ProjectAssignmentConfiguration() {     HasKey(u => new { u.Employee.EmployeeId, u.Project.ProjectId }); } 

So how do you set up an entity where the join table has a primary key that is composed of foreign keys?

like image 150
djskinner Avatar answered Sep 25 '22 00:09

djskinner


I will try to explain it step by step, using the following Entity

public class Account {     public int AccountId1 { get; set; }     public int AccountId2 { get; set; }     public string Description { get; set; } } 
  1. Create a class derived from the EntityTypeConfiguaration<TEntity> Object to override the conventions

    class AccountEntityTypeConfiguration : EntityTypeConfiguration<Account> {      public AccountEntityTypeConfiguration()     {       // The Key       // The description of the HasKey Method says       // A lambda expression representing the property to be used as the primary key.       // If the primary key is made up of multiple properties then specify an anonymous type including the properties.       // Example C#: k => new { k.Id1, k.Id2 }       // Example VB: Function(k) New From { k.Id1, k.Id2 }       this.HasKey(k => new { k.AccountId1, k.AccountId2 } );  // The Key        // Maybe the key properties are not sequenced and you want to override the conventions       this.Property(p => p.AccountId1).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);       this.Property(p => p.AccountId2).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);        this.Property(p => p.Description).IsRequired();  // This property will be required       this.ToTable("Account");  // Map the entity to the table Account on the database     } } 
  2. When create the class derived from the DbContext Object, override OnModelCreating Method and add a new AccountEntityTypeConfiguration object to the Configurations of the model Builder.

    public class MyModelAccount : DbContext {     public DbSet<Account> Accounts { get; set;}      protected override void OnModelCreating(DbModelBuilder modelBuilder)     {         // Add a new AccountEntityTypeConfiguration object to the configuration of the model, that will be applied once the model is created.          modelBuilder.Configurations.Add(new AccountEntityTypeConfiguration());     }  } 

Hope it helps you!

like image 35
sergioacortes Avatar answered Sep 25 '22 00:09

sergioacortes