38

I'm using Entity Framework Codefirst to create my Database. The default Primary key with the schema name dbo.pk_Jobs seems to upset access 2007 when I connect to it over ODBC. If I manually edit the name and remove the schema name and rename this Primary Key to pk_jobs, Access can now read the table.

Can I specify the Primary Key name to not include the name of the schema using Fluent Api, Data Attributes or any other method.

public class ReportsContext : DbContext
{
    public DbSet<Job> Jobs { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Job>().ToTable("Jobs");
        modelBuilder.Entity<Job>().HasKey(j => j.uuid);

        base.OnModelCreating(modelBuilder);
    }
}
public class Job
{
    public Guid uuid{ get; set; }
    public int active{ get; set; }
}
Arsen Mkrtchyan
  • 49,896
  • 32
  • 148
  • 184
tourdownunder
  • 1,779
  • 4
  • 22
  • 34

5 Answers5

65

If you want to specify the column name and override the property name, you can try the following:

Using Annotations

public class Job
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column("CustomIdName")]
    public Guid uuid { get; set; }
    public int active { get; set; }
}

Using Code First

    protected override void OnModelCreating(DbModelBuilder mb)
    {
        base.OnModelCreating(mb);

        mb.Entity<Job>()
            .HasKey(i => i.uuid);
        mb.Entity<Job>()
          .Property(i => i.uuid)
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
          .HasColumnName("CustomIdName");
    }

Inside Migration Configuration

public partial class ChangePrimaryKey : DbMigration
{
    public override void Up()
    {
        Sql(@"exec sp_rename 'SchemaName.TableName.IndexName', 'New_IndexName', 'INDEX'");
    }

    public override void Down()
    {
        Sql(@"exec sp_rename 'SchemaName.TableName.New_IndexName', 'Old_IndexName', 'INDEX'");
    }
}
cubski
  • 3,218
  • 1
  • 31
  • 33
  • The default Column name of uuid is ok, though I need to set/override the Primary Key Name. – tourdownunder Nov 29 '12 at 00:56
  • I see. I believe Jeff Siver's suggestion is the way to go. If you use code first migration, you can place your T-SQL rename query there. More of details of sp_rename found here http://msdn.microsoft.com/en-us/library/ms188351.aspx. – cubski Nov 29 '12 at 10:19
  • thanks @cubski. This did the trick. Needed to use square braces in the rename command for it to work. execute sp_rename @objname=N'[dbo].[PK_dbo.Jobs]', @newname=N'[PK_Jobs]'--,@objtype=N'INDEX' – tourdownunder Nov 30 '12 at 20:35
  • @darwindave Good to know, btw, is it necessary to add the "@objname","@newname", "@objtype" for it to work? – cubski Nov 30 '12 at 20:51
  • objtype is actually commented out with -- so no it's not needed. As for naming the parameters I struggled for hours to get this working it was something I tried, – tourdownunder Dec 01 '12 at 01:13
  • @darwindave yeah my mistake, didn't actually tried to run the migration code. – cubski Dec 01 '12 at 01:35
10

You can use the Key attribute to specify the parts of the primary key. So your Job class might be

public class Job
{
    [Key]
    public Guid uuid{ get; set; }
    public int active{ get; set; }
}

The data annotation attributes are defined in the System.ComponentModel.DataAnnotations namespace

Chris Dunaway
  • 10,974
  • 4
  • 36
  • 48
2

If I understand, you are asking how to change the name of the primary key column used by Entity Framework. The following addition to your HasKey statement should take care of this:

modelBuilder.Entity<Job>().Property(j => j.uuid).HasColumnName("pk_Jobs")
Jeff Siver
  • 7,434
  • 30
  • 32
  • I believe this is the answer though I get this error: Error 7 'System.Data.Entity.ModelConfiguration.Configuration.EntityMappingConfiguration' does not contain a definition for 'MapKey' and no extension method 'MapKey' accepting a first argument of type 'System.Data.Entity.ModelConfiguration.Configuration.EntityMappingConfiguration' could be found (are you missing a using directive or an assembly reference?) C:\Work\Freelancing\dahhal\Reports\dahhal.AccessDbManager\AccessDb.cs 349 71 dahhal.AccessDbManager – tourdownunder Nov 28 '12 at 23:09
  • Sorry - that syntax was for foreign keys. I've changed the code to specifying a column name for any property. – Jeff Siver Nov 28 '12 at 23:31
  • I tried modelBuilder.Entity().HasKey(j => j.uuid).Property(j => j.uuid).HasColumnName("pk_Jobs"); Though this just renames the uuid to pk_Jobs. I need to set the key name and not the column name – tourdownunder Nov 28 '12 at 23:57
  • 2
    Sorry, I think I misunderstood what you are asking. If I understand it now, you are looking for a way to name the primary key constraint when EF is used to generate the database. Sorry, but there is no easy way to do that. Have a look at this question, http://stackoverflow.com/questions/8476035/entity-framework-4-1-name-constraints, for one possible approach. – Jeff Siver Nov 29 '12 at 02:18
1

(This is a complement to the answer/comments by @Jeff Sivers and @cubski.)

As far as I know you can't specify the PK name with Data Attribute. Sometimes I need to get rid of the dbo. part of the name and I then use a manually edited code first migration to change the name, like this:

public partial class ChangeNameOnPKInCustomers : DbMigration
{
    private static string fromName = "PK_dbo.Customers";    // Name to change

    private static string toName = fromName.Replace("dbo.", "");

    public override void Up()
    {
        Sql($"exec sp_rename @objname=N'[dbo].[{fromName}]', @newname=N'{toName}'");
        // Now the PK name is "PK_Customers".
    }

    public override void Down()
    {
        Sql($"exec sp_rename @objname=N'[dbo].[{toName}]', @newname=N'{fromName}'");
        // Back to "PK_dbo.Customers".
    }
}
savehansson
  • 453
  • 7
  • 14
0

When you add an explicit migration using Code First, you get a .cs file with the name of the migration which is a partial class with a base class DbMigration.

For your Primary Key Constraint, you have either DropPrimaryKey or AddPrimaryKey function depending on what you are trying to do. My problem was with DropPrimaryKey as my Db had different name for the Primary Key.

Both these functions have overloads to take the name of the PK so that you could explicitly specify the name of the PK. Worked fine for me for DropPrimaryKey with explicit PK name. The argument being object anonymousArguments which is by default null.