EF复合主键中的一对多

时间:2018-11-27 00:45:52

标签: c# entity-framework-core ef-fluent-api ef-core-2.0

我在现有数据库中有三层表,当我获得中层数据时,我试图包括最下层的记录...这应该是一对多的关系-对于带有产品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。如果我删除包含,它将正常工作。

1 个答案:

答案 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。