我在现有数据库中有三层表,当我获得中层数据时,我试图包括最下层的记录...这应该是一对多的关系-对于带有产品y的装运x是z分析结果。
public class Shipment
{
[Key]
public int Id { get; set; }
public string ShipName { get; set; }
public DateTime ShipmentDate { get; set; }
}
public class ShipmentDetails
{
[ForeignKey ("ShipmentId")]
public int Id { get; set; }
[ForeignKey ("ProductId")]
public int ProductId { get; set; }
Public double Weight { get; set; }
public virtual ShippingAnalysis Analysis { get; set; }
}
public class ShipmentAnalysis
{
[ForeignKey ("ShipmentId")]
public int Id { get; set; }
[ForeignKey ("ProductId")]
public int TenantId { get; set; }
[ForeignKey ("MetricId")]
public int MetricId { get; set; }
Public double Result { get; set; }
}
我正在使用流利的api方式定义复合主键。
modelBuilder.Entity<ShippingDetail>()
.HasKey(c => new { c.ShipmentId, c.ProductlId });
modelBuilder.Entity<ShippingAnalysis>()
.HasKey(c => new { c.ShipmentId, c.ProductId, c.MetricId });
我获得了带有(一对多)分析记录的发运明细。
var results = _context.ShippingDetail.Include(sd => sd.Analysis)
.Where(sd => sd.ShipmentId == id);
这不会在邮递员中返回结果,而是通过浏览器返回格式错误的JSON。如果我删除包含,它将正常工作。
答案 0 :(得分:2)
问题不是组合键,而是导航属性(因此关系定义)。 (一侧)(如果存在)的导航属性必须是 collection ,(许多)一侧的导航属性应该是 reference -参见Relationships - Definition of Terms。
根据
modelBuilder.Entity<ShippingDetail>()
.HasKey(c => new { c.ShipmentId, c.ProductlId });
modelBuilder.Entity<ShippingAnalysis>()
.HasKey(c => new { c.ShipmentId, c.ProductId, c.MetricId });
关系应为ShippingDetail
(一个)->(很多)ShippingAnalysis
,因此
public virtual ShippingAnalysis Analysis { get; set; }
ShippingDetail
的属性必须为
public virtual ICollection<ShippingAnalysis> Analysis { get; set; }
这足以使EF Core确定正确的复合FK列。但是,如果您要百分百确定(明确表示永远不会受伤),请添加以下流利的配置:
modelBuilder.Entity<ShippingDetail>()
.HasMany(e => e.Analysis)
.WithOne() // make sure to specify navigation property if exists, e.g. e => e.NavProp
.HasForeignKey(e => new { e.ShipmentId, e.ProductId });
P.S。删除所有这些[ForeignKey]
数据注释。根据是将它们应用于FK属性还是导航属性,它们会执行不同的操作,并且请确保不要按照您的想法进行操作,有时可能会导致意外的行为。根据我在EF Core关系方面的经验,要么让EF Core约定发挥作用,要么使用流畅的API。