EF在复合主键的一部分上一对多
EF one to many on part of composite primary key
我在现有数据库中有三层表,我试图在获取中间层数据时包括底层记录...这应该是一对多关系 - 对于 shipment x 和 product 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; }
}
我正在使用流畅的 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);
这不是 return 邮递员的结果,而是通过浏览器 return 格式错误的 JSON。如果我删除包含,它工作正常。
问题不在于复合键,而在于导航属性(因此关系定义)。在(一)侧(如果存在)的导航 属性 必须是 集合 ,在(多)侧的导航 属性 应该是 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.
我在现有数据库中有三层表,我试图在获取中间层数据时包括底层记录...这应该是一对多关系 - 对于 shipment x 和 product 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; }
}
我正在使用流畅的 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);
这不是 return 邮递员的结果,而是通过浏览器 return 格式错误的 JSON。如果我删除包含,它工作正常。
问题不在于复合键,而在于导航属性(因此关系定义)。在(一)侧(如果存在)的导航 属性 必须是 集合 ,在(多)侧的导航 属性 应该是 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.