【问题标题】:EF one to many on part of composite primary keyEF 一对多组合主键的一部分
【发布时间】:2019-04-28 16:40:15
【问题描述】:

我在现有数据库中有三层表,当我获得中间层数据时,我试图包含底层记录...这应该是一对多的关系 - 用于装运 x 和产品 y是 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; }
}

我正在使用 fluent 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。如果我放弃包含,它工作正常。

【问题讨论】:

  • 我建议不要使用复合键,而是使用专用 PK 并添加唯一约束以避免重复
  • 谢谢@Johnb,但我不确定这将如何帮助我获得包含运输详细信息结果的一对多分析记录?

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


【解决方案1】:

问题不是复合键,而是导航属性(因此是关系定义)。 (一)侧(如果存在)的导航属性必须是 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 });

附:删除所有这些 [ForeignKey] 数据注释。根据是应用于 FK 属性还是导航属性,它们会做不同的事情,并且肯定不会按照您的想法做,有时实际上可能会导致意外行为。根据我对 EF Core 关系的经验,要么让 EF Core 约定发挥作用,要么使用流畅的 API。

【讨论】:

  • 我已根据您的上述代码将其放置到位,并删除了 ShippingDetail 实体上的 FK 内容。我没有收到错误提示“实体类型 'ShippinDetail' 需要定义主键。”根据我的原始帖子,我确实有一个流利的 API 复合外语,但是当我输入您的代码时已经将其注释掉。所以......我取消了它的注释,然后没有错误,但它超时并返回'['。我哪里错了?
猜你喜欢
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
相关资源
最近更新 更多