2013-08-26 143 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