2013-08-26 147 views
2

我有一个POCO模型,主键属性映射到具有不同名称的列上。实体框架迁移:PrimaryKey

的模型是这样的:

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]) 

任何想法?这是一个明显的错误?

+0

FWIW,对于TableBuilder中的ForeignKey和Index似乎存在同样的错误。 –

回答

2

为了告诉实体框架的SQL列名查询该EF会产生必须将其指定为模型,而不是在移民,无论是与数据注解...

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

.. .or或者使用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]) 
    ) 
    
+0

不幸的是,这意味着我的模型不再是POCO了。我不喜欢将这些属性添加到我的模型中,因为它将它紧密地耦合到EF。另外,name参数完全不影响DDL脚本,正如我的文章中所见。 –

+0

哦,我实际上使用Fluent API来映射我的实体。这里的映射不是问题。这是生成的DDL错误。 –

+0

@ErnstKuschke:如果您从迁移代码中移除了'name:“intTransactionID”',DDL仍然错误吗? – Slauma

0
+1

那位回答了这个问题的人不是EF开发团队的成员,我不会将他写为“确认”,更不用说作为意见。而且他提出了和我一样的解决方案。我不会将它称为“解决方法”,因为模型元数据(带注释或Fluent API)中的映射非常重要,因此EF可以使用正确的列名创建SQL语句。您无法使用迁移来定义此映射,这不是其目的。目的是更新数据库模式,迁移不知道如何将此模式映射到模型类。 – Slauma

+0

@Slauma你似乎不了解这个问题。他或你提出的解决方案不是解决方案。正如你所建议的那样,我的类*被映射。该错误在映射中不是*,而是在Migrations中,它忽略了给出列的任何自定义名称。这使得Migrations在EF中无用。 –

+0

假设你有一个类,并为它添加一个'Remark'属性,你可以用Fluent API调用'.HasColumnName(“X”)',因为你希望表中的列名为“X”而不是'Remark' 。你这样做是因为当你用'Where(a => a.Remark ==“SomeText”)运行一个查询时'你告诉EF它必须被转换成一个SQL'WHERE X = N'SomeText''(注意:* * X **,而不是**备注**)。然后你调用'add-migration',并创建一个将向表中添加一个名为“X”的列(**不是“备注”**)的迁移。 **为什么你想在这个迁移类中把这个列重命名为“Y”?** – Slauma

0

我使用两个映射选项(流利和属性)进行测试。在这两种情况下,使用添加迁移生成迁移时,任何自定义映射都会被完全忽略。

映射工作,但迁移不是。这意味着使用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()。

+0

“*我使用两种映射选项(流利和属性)进行测试,在两种情况下,使用添加迁移生成迁移时,任何自定义映射都会被完全忽略*换句话说,您的确和我在在我的答案编辑部分,你没有得到我的结果?那么,如果您可以提供可重现的样本,那么您可以*真正*报告为错误。 – Slauma