2014-09-30 48 views
0

我試圖使用Fluent API和.Include()獲取一些嵌套的數據。我正在使用的數據庫沒有正常化,我無法控制它。實體框架(代碼優先)一對多 - 生成額外的字段,而不是使用映射的鍵

「父」表是TASK,「子」表是STOCK_MOVEMENT,其中「許多股票移動到一個任務」關係。

該映射應該來自TASK,其複合關鍵字{「TSK_SITE」,「TSK_TYPE」}到STOCK_MOVEMENT上,複合關鍵字{「MOV_SITE」,「MOV_TYPE」,「MOV_MOVE」}。

article here似乎最適合我的任務,特別是「配置複合外鍵」部分。不幸的是,我似乎沒有得到我的intellisense爲「HasForeignKey」系列提示的預期字段,所以我不得不嘗試別的東西......(想法歡迎!)

我試過的是這樣的:

  this.HasRequired(sm => sm.TestTask) 
      .WithMany(t => t.Movements) 
      .Map(m => m.MapKey("MOV_SITE", "MOV_TYPE")); 

試圖「HasRequired」和「HasOptional」...但是,最終由EF生成的SQL包含額外的字段,而不是根據我指定的外鍵映射。

任何人都可以解釋我應該如何改變我的映射以獲得正確的SQL嗎? 指導性問題也非常受歡迎。

我附上以下所有相關代碼...

非常感謝!

維多利亞

public class TestTask : IMyObject 
{ 
    public TestTask() 
    { 
     this.KeyFields = new string[] { "Site", "TaskType" }; 

     this.Movements = new HashSet<TestMovement>(); 
    } 

    public string Site { get; set; } 
    public string TaskType { get; set; } 
    public string Key { get; set; } 

    public virtual HashSet<TestMovement> Movements { get; set; } 

    //... more code 
} 

internal partial class TestTask_Mapping : EntityTypeConfiguration<TestTask> 
{ 
    public TestTask_Mapping() 
    { 
     this.HasKey(t => new { t.Site, t.TaskType }); 

     this.ToTable("TASK"); 

     this.Property(t => t.Site) 
      .HasColumnName("TSK_SITE") 
      .IsRequired(); 

     this.Property(t => t.TaskType) 
      .HasColumnName("TSK_TYPE") 
      .IsRequired(); 

     this.Property(t => t.Key) 
      .HasColumnName("TSK_REF"); 
    } 
} 

public class TestMovement : IMyObject 
{ 
    public TestMovement() 
    { 
     this.KeyFields = new string[] { "Site", "MoveType" }; 
    } 

    public string Site { get; set; } 
    public string MoveType { get; set; } 
    public string Key { get; set; } 

    public virtual TestTask TestTask { get; set; } 

    // ... more code 
} 

public class TestStockMovement_Mapping : EntityTypeConfiguration<TestMovement> 
{ 
    public TestStockMovement_Mapping() 
    { 
     this.HasKey(t => new { t.Site, t.MoveType }); 

     this.HasRequired(sm => sm.TestTask) 
      .WithMany(t => t.Movements) 
      .Map(m => m.MapKey("MOV_SITE", "MOV_TYPE")); 

     this.Property(t => t.Site) 
      .IsRequired(); 

     this.Property(t => t.MoveType) 
      .IsRequired(); 

     this.ToTable("STOCK_MOVEMENT"); 

     //this.Property(t => t.Site).HasColumnName("MOV_SITE"); 
     //this.Property(t => t.MoveType).HasColumnName("MOV_TYPE"); 
     this.Property(t => t.Key).HasColumnName("MOV_MOVE"); 

    } 
} 

// In DbContext... 

public DbSet<TestTask> TestTasks { get; set; } 
public DbSet<TestMovement> TestStockMovements { get; set; } 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Configurations.Add(new TestTask_Mapping()); 
    modelBuilder.Configurations.Add(new TestStockMovement_Mapping()); 
} 

// In the appropriate method in the repository ... 

IQueryable<TestTask> testTasks = context.TestTasks.Include(t => t.Movements); 

// Where testTasks results in the SQL with incorrect foreign key field references 
// (please see the picture that tells a thousand words below)... 

Incorrect foreign key mapped by EF


爲了闡明在數據庫字段和所涉及的表:我只提及用作鍵的簡化問題列:

1)「TASK 「表包含構成其組合鍵(+更多列)的列」TSK_SITE「和」TSK_TYPE「。

2)「STOCK_MOVEMENT」表包含列「MOV_SITE」,「MOVE_TYPE」和「MOV_MOVE」,它們是組合鍵的一部分(+更多列)。我沒有在我的映射中使用「MOV_MOVE」,因爲父TASK表中沒有等效列。

我期望爲每個TASK記錄檢索一個或多個STOCK_MOVEMENT記錄。

+0

如果'{「MOV_SITE」,「MOV_TYPE」}'是'STOCK_MOVEMENT'表中的主鍵,那麼TASK'表的外鍵是什麼?如果關係是一對多的,它不能再是「{」MOV_SITE「,」MOV_TYPE「}(如你的映射所說)。如果PK和FK是相同的,這隻能是一對一的關係。 – Slauma 2014-09-30 18:19:29

+0

非常感謝回覆我的問題,Slauma!我在原始文章中添加了一個編輯,闡明瞭STOCK_MOVEMENT表中有一列是該表的組合鍵的一部分,但是我沒有將其添加到映射關係中。在父TASK表中沒有與該列等效的內容,因此沒有任何內容可映射到該列。我該如何(我應該)在我的代碼中創建一對多的帳戶列... – Victoria 2014-09-30 19:34:04

回答

3

TestTask的映射似乎是正確的。對於TestMovement映射必須映射全鍵與所有三個部分:

this.HasKey(t => new { t.Site, t.MoveType, t.Key }); 

然後映射的列名,並設置所有的三個關鍵性能需要(鍵列無法可空):

this.Property(t => t.Site) 
    .HasColumnName("MOV_SITE") 
    .IsRequired(); 

this.Property(t => t.MoveType) 
    .HasColumnName("MOV_TYPE") 
    .IsRequired(); 

this.Property(t => t.Key) 
    .HasColumnName("MOV_MOVE") 
    .IsRequired(); 

然後 - 最重要的是 - 請勿將MapKey用於關係映射,因爲您的外鍵列是模型類中的屬性。在這種情況下,你總是必須使用HasForeignKey

this.HasRequired(sm => sm.TestTask) 
    .WithMany(t => t.Movements) 
    .HasForeignKey(t => new { t.Site, t.MoveType }); 

我知道你說,HasForeignKey智能感知沒有提供預期的屬性(但代碼編譯呢?)。這是你需要解決的另一個問題。但使用MapKey是沒有解決方案,並沒有給你的模型和映射無處可去。

+0

感謝您的詳細說明,Slauma,我會在幾個小時內試用它們...... – Victoria 2014-10-01 08:14:12

+0

已經開始「從頭開始」,現在智能感知正在發揮作用,並且您的建議已成爲現實!謝謝你的幫助,一切正常! – Victoria 2014-10-03 09:08:15

相關問題