【发布时间】:2014-11-25 01:19:57
【问题描述】:
我正在尝试使用 Fluent API 和 .Include() 获取一些嵌套数据。我正在使用的数据库未标准化,我无法控制它。
“父”表是 TASK,“子”表是 STOCK_MOVEMENT,具有“许多库存移动到一个任务”的关系。
映射应该是从具有复合键 { "TSK_SITE", "TSK_TYPE" } 的 TASK 到具有复合键 { "MOV_SITE", "MOV_TYPE", "MOV_MOVE" } 的 STOCK_MOVEMENT。
article here 似乎最适合我手头的任务,尤其是“配置复合外键”部分。不幸的是,我的智能感知似乎没有为“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)...
为了澄清所涉及的数据库字段和表:我只提到了用作键的列以简化问题:
1)“TASK”表包含“TSK_SITE”和“TSK_TYPE”列,它们构成了它的复合键(+更多列)。
2)“STOCK_MOVEMENT”表包含“MOV_SITE”、“MOVE_TYPE”和“MOV_MOVE”列,它们构成其复合键的一部分(+更多列)。我没有在映射中使用“MOV_MOVE”,因为那里在父 TASK 表中没有等效列。
我应该为每个 TASK 记录检索一个或多个 STOCK_MOVEMENT 记录。
【问题讨论】:
-
如果
{ "MOV_SITE", "MOV_TYPE" }是STOCK_MOVEMENT表中的主键,那么TASK表的外键是什么?如果关系是一对多的,它就不能再次是{ "MOV_SITE", "MOV_TYPE" }(正如你的映射所说)。如果 PK 和 FK 相同,则只能是一对一的关系。 -
非常感谢您回答我的问题,Slauma!我在我的原始帖子中添加了一个编辑,澄清在 STOCK_MOVEMENT 表中还有一列是该表的复合键的一部分,但我没有添加到映射关系中。父 TASK 表中没有与该列等效的列,因此没有可映射的内容。我如何(应该)在我的代码中考虑该列以创建一对多?...
标签: c# entity-framework code-first composite-key