【问题标题】:How to Specify Primary Key Name in EF-Code-First如何在 EF-Code-First 中指定主键名称
【发布时间】:2012-11-16 10:45:19
【问题描述】:

我正在使用 Entity Framework Codefirst 来创建我的数据库。当我通过 ODBC 连接到 2007 时,具有模式名称 dbo.pk_Jobs 的默认主键似乎扰乱了访问 2007。如果我手动编辑名称并删除架构名称并将此主键重命名为 pk_jobs,Access 现在可以读取该表。

我能否使用 Fluent Api、数据属性或任何其他方法指定主键名称以不包含架构名称。

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

【问题讨论】:

    标签: c# .net sql-server entity-framework ef-code-first


    【解决方案1】:

    如果要指定列名并覆盖属性名,可以尝试如下:

    使用注解

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

    使用代码优先

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

    内部迁移配置

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

    【讨论】:

    • uuid 的默认列名是可以的,虽然我需要设置/覆盖主键名。
    • 我明白了。我相信 Jeff Siver 的建议是可行的。如果您使用代码优先迁移,则可以将 T-SQL 重命名查询放在那里。有关 sp_rename 的更多详细信息,请参见 msdn.microsoft.com/en-us/library/ms188351.aspx
    • 感谢@cubski。这成功了。需要在重命名命令中使用方括号才能工作。执行 sp_rename @objname=N'[dbo].[PK_dbo.Jobs]', @newname=N'[PK_Jobs]'--,@objtype=N'INDEX'
    • @darwindave 很高兴知道,顺便说一句,是否有必要添加“@objname”、“@newname”、“@objtype”才能使其工作?
    • objtype 实际上被注释掉了 -- 所以不需要它。至于命名参数,我花了好几个小时努力让它工作,这是我尝试过的,
    【解决方案2】:

    您可以使用 Key 属性来指定主键的各个部分。所以你的 Job 类可能是

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

    数据注解属性定义在System.ComponentModel.DataAnnotations namespace

    【讨论】:

    • 如果我可以覆盖由数据库自动生成的键名,那就没问题了。虽然 Key 属性似乎没有带参数。
    • @darwindave - 请参阅下面 cubski 的回答
    【解决方案3】:

    如果我理解,您是在问如何更改实体框架使用的主键列的名称。您的 HasKey 语句中的以下添加应该解决这个问题:

    modelBuilder.Entity<Job>().Property(j => j.uuid).HasColumnName("pk_Jobs")
    

    【讨论】:

    • 我相信这是答案,尽管我收到此错误:错误 7 'System.Data.Entity.ModelConfiguration.Configuration.EntityMappingConfiguration' does not contain a definition for 'MapKey ' 并且没有扩展方法 'MapKey' 接受类型为 'System.Data.Entity.ModelConfiguration.Configuration.EntityMappingConfiguration' 的第一个参数(您是否缺少 using 指令或程序集引用?) C:\Work\Freelancing\dahhal\Reports\dahhal.AccessDbManager\AccessDb.cs 349 71 dahhal.AccessDbManager
    • 抱歉 - 该语法是用于外键的。我已将代码更改为为任何属性指定列名。
    • 我试过 modelBuilder.Entity().HasKey(j => j.uuid).Property(j => j.uuid).HasColumnName("pk_Jobs");虽然这只是将 uuid 重命名为 pk_Jobs。我需要设置键名而不是列名
    • 对不起,我想我误解了你的要求。如果我现在明白了,您正在寻找一种在使用 EF 生成数据库时命名主键约束的方法。抱歉,没有简单的方法可以做到这一点。看看这个问题,stackoverflow.com/questions/8476035/…,寻找一种可能的方法。
    【解决方案4】:

    (这是对@Jeff Sivers 和@cubski 的答案/cmets 的补充。)

    据我所知,您无法使用数据属性指定 PK 名称。有时我需要去掉名称中的dbo. 部分,然后使用手动编辑的代码先迁移来更改名称,如下所示:

    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".
        }
    }
    

    【讨论】:

      【解决方案5】:

      当您使用 Code First 添加显式迁移时,您会获得一个带有迁移名称的 .cs 文件,该文件是具有基类 DbMigration 的部分类。

      对于您的主键约束,您可以使用 DropPrimaryKey 或 AddPrimaryKey 函数,具体取决于您要执行的操作。我的问题在于 DropPrimaryKey,因为我的 Db 的主键名称不同。

      这两个函数都有重载来获取 PK 的名称,以便您可以显式指定 PK 的名称。对于具有显式 PK 名称的 DropPrimaryKey 对我来说效果很好。参数是对象 anonymousArguments,默认为 null。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-17
        • 1970-01-01
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多