116

I'm creating a POCO model to use with entity framework code first CTP5. I'm using the <key()> 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?

Edit: look at @kara's answer for an updated solution.

Thanks!

6 Answers 6

173

NOTE: As of 2019 this answer became non-valid for later EntityFramework versions.

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.

Sign up to request clarification or add additional context in comments.

1 Comment

InvalidOperationException: Entity type 'XXX' has composite primary key defined with data annotations. To set composite primary key, use fluent API.
75

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 
        });
    }
}

3 Comments

Thanks - both methods do work fine. I prefer the Attributes because I'm generating my classes from code, and attributes are much more concise.
I personally also add the Propety(x...).HasColumnOrder(0...n) to each of the keyed properties. Is that good, bad, indifferent?
This answer will work for latest EF-versions.
16

In EF Core 7.0 a new attribute for classes [PrimaryKey] was introduced.

Example:

[PrimaryKey(nameof(FirstName),nameof(LastName))]
public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string SomeProperty { get; set; }
}

This way, you don't have to use the fluent-api again.

1 Comment

Thank you @kara. This question was asked in 2011, referring to ef5 and was consistently popular. It documents the change through ef6 and now efc7, and should be turned into a wiki entry...
13

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());
    }
}

Comments

1

In EF or EF Core, the Column Order attribute is not supported for specifying key order, so the best practice is to configure composite keys in the OnModelCreating method of your DbContext.

public class MyEntity
{
    public int MyFirstKeyProperty { get; set; }

    public int MySecondKeyProperty { get; set; }

    public string MyThirdKeyProperty { get; set; }

    // Other properties
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>()
        .HasKey(e => new { e.MyFirstKeyProperty, e.MySecondKeyProperty, e.MyThirdKeyProperty });

    base.OnModelCreating(modelBuilder);
}

Comments

1

Use as a anonymous object:

modelBuilder.Entity<UserExamAttemptQuestion>().ToTable("Users").HasKey(o => new { o.UserId, o.Username }); 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.