实体框架迁移:PrimaryKey

时间:2013-08-26 14:39:35

标签: .net entity-framework ef-migrations

我有一个POCO模型,其主键属性映射到具有不同名称的列。

该模型类似于:

public class Transaction
{
    public long Id { get; set; }
    //....more props
}

因此迁移看起来像:

CreateTable(
    "dbo.dtlTransactions",
    c => new
        {
            Id = c.Long(nullable: false, identity: true, name: "intTransactionID"),
            //...more cols
        })
        .PrimaryKey(t => t.Id);

然而,在运行迁移时,我得到:

  

System.Data.SqlClient.SqlException(0x80131904):列名'Id'   目标表或视图中不存在。

在生成sql时似乎没有使用columnbuilder的name属性。迁移的-verbose选项为我提供了这个sql:

CREATE TABLE [dbo].[dtlTransactions] (
[intTransactionID] [bigint] NOT NULL IDENTITY,
--...other cols
CONSTRAINT [PK_dbo.dtlTransactions] PRIMARY KEY ([Id])

有什么想法吗?这是一个明显的错误吗?

3 个答案:

答案 0 :(得分:2)

为了告诉实体框架EF将生成的SQL查询的列名,您必须为模型指定它,而不是在迁移中指定数据注释......

[Column("intTransactionID")]
public long Id { get; set; }

...或使用Fluent API:

modelBuilder.Entity<Transaction>()
    .Property(t => t.Id)
    .HasColumnName("intTransactionID");

以这种方式定义列名后,您不再需要在迁移代码中定义它。

您正在使用的Migration类中的name参数会影响发送到数据库的DDL脚本,但不会告诉EF模型元数据该列具有其他名称。

老实说,我不知道任何用例,迁移代码中的name参数可能有用。

修改

我已经测试过它可以使用以下示例:

  • 我用你的班级:

    public class Transaction
    {
        public long Id { get; set; }
    }
    
  • 在此上下文中,我使用Fluent API定义列名:

    public class MyContext : DbContext
    {
        public DbSet<Transaction> Transactions { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Transaction>()
                .ToTable("dtlTransactions");
    
            modelBuilder.Entity<Transaction>()
                .Property(t => t.Id)
                .HasColumnName("intTransactionID");
        }
    }
    
  • 然后我在包管理器控制台上运行enable-migrationsadd-migration InitialSchema

  • 我得到了这个DbMigration课程:

    public partial class InitialSchema : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.dtlTransactions",
                c => new
                  {
                      intTransactionID = c.Long(nullable: false, identity: true),
                  })
                .PrimaryKey(t => t.intTransactionID);
        }
    
        public override void Down()
        {
            DropTable("dbo.dtlTransactions");
        }
    }
    
  • 然后我在包管理器控制台上调用update-database -script并获取该表的DDL脚本 - 这是正确且预期的脚本:

    CREATE TABLE [dbo].[dtlTransactions] (
        [intTransactionID] [bigint] NOT NULL IDENTITY,
        CONSTRAINT [PK_dbo.dtlTransactions] PRIMARY KEY ([intTransactionID])
    )
    

答案 1 :(得分:0)

答案 2 :(得分:0)

我使用两种映射选项(流畅和属性)进行了测试。在这两种情况下,使用Add-Migration生成迁移时,任何自定义映射都将被完全忽略。

映射有效,但迁移不起作用。这意味着在将EF用作ORM时,迁移不可用。

一种解决方法是手动制作迁移,而不是使用 TableBuilder ,使用 DbMigration 方法:

而不是

CreateTable(
    "dbo.dtlTransactions",
    c => new
        {
            Id = c.Long(nullable: false, identity: true, name: "intTransactionID"),
            //...more cols
        })
        .PrimaryKey(t => t.Id, name: "intTransactionID");

你可以使用:

CreateTable(
    "dbo.dtlTransactions",
    c => new
        {
            Id = c.Long(nullable: false, identity: true, name: "intTransactionID"),
            //...more cols
        });
AddPrimaryKey("dbo.dtlTransactions", "intTransactionId");

TableBuilder.Index()也是如此 - 而不是使用CreateIndex()。