100

I'm creating a POCO model to use with entity framework code first CTP5. I'm using the decoration to make a property map to a PK column. But how can I define a PK on more then one column, and specifically, how can I control order of the columns in the index? Is it a result of the order of properties in the class?

Thanks!

GilShalit
  • 5,648
  • 9
  • 40
  • 62

4 Answers4

159

You can specify the column order in the attributes, for instance:

public class MyEntity
{
    [Key, Column(Order=0)]
    public int MyFirstKeyProperty { get; set; }

    [Key, Column(Order=1)]
    public int MySecondKeyProperty { get; set; }

    [Key, Column(Order=2)]
    public string MyThirdKeyProperty { get; set; }

    // other properties
}

If you are using the Find method of a DbSet you must take this order for the key parameters into account.

Slauma
  • 171,778
  • 59
  • 393
  • 415
  • 1
    InvalidOperationException: Entity type 'XXX' has composite primary key defined with data annotations. To set composite primary key, use fluent API. – Luca Ziegler Nov 17 '19 at 18:07
62

To complete the correct answer submitted by Slauma, you can use the HasKey method to specify an order for composite primary keys as well:

public class User
{        
    public int UserId { get; set; }       
    public string Username { get; set; }        
}        

public class Ctp5Context : DbContext
{
    public DbSet<User> Users { get; set; }        

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasKey(u => new 
        { 
            u.UserId, 
            u.Username 
        });
    }
}
Morteza Manavi
  • 32,518
  • 6
  • 97
  • 82
  • 2
    Thanks - both methods do work fine. I prefer the Attributes because I'm generating my classes from code, and attributes are much more concise. – GilShalit Feb 10 '11 at 08:29
  • I personally also add the Propety(x...).HasColumnOrder(0...n) to each of the keyed properties. Is that good, bad, indifferent? – Suamere Mar 26 '15 at 15:13
9

If, like me, you prefer to use a configuration file you can do that in this way (based on Manavi's example):

public class User
{
    public int UserId { get; set; }
    public string Username { get; set; }
}  

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        ToTable("Users");
        HasKey(x => new {x.UserId, x.Username});
    }
}

Obviously you have to add the configuration file to your context:

public class Ctp5Context : DbContext
{
    public DbSet<User> Users { get; set; }        

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
         modelBuilder.Configurations.Add(new UserConfiguration());
    }
}
Daniele Armanasco
  • 7,030
  • 9
  • 41
  • 53
0

Use as a anonymous object:

modelBuilder.Entity<UserExamAttemptQuestion>().ToTable("Users").HasKey(o => new { o.UserId, o.Username }); 
Kos
  • 4,483
  • 8
  • 35
  • 39