2014-09-30 61 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

相关问题