一对一 HasRequired 配置不起作用

One to One HasRequired configuration not working

我有两组对象:CouponDiscountScheme
每个都有一个 {Type}Action 的连接对象和相同的配置。
请求 Coupon 时,我没有得到任何回复, 但是 DiscountScheme 的相同查询按预期工作

类 的精简版(table 的完整代码和 sql 可以在 here 中找到):

public class CouponAction
{
    public int Id { get; set; }
    public virtual Coupon Coupon { get; set; }
}

public class Coupon
{
    public int Id { get; set; }
    public virtual CouponAction Action { get; set; }
}

public class DiscountSchemeAction
{
    public int Id { get; set; }
    public virtual DiscountScheme DiscountScheme { get; set; }
}

public class DiscountScheme
{
    public int Id { get; set; }
    public virtual DiscountSchemeAction Action { get; set; }
}

配置:

public class CouponActionMap : EntityTypeConfiguration<CouponAction>
{
    public CouponActionMap()
    {
        ToTable("CouponAction");
    }
}

public class CouponMap : EntityTypeConfiguration<Coupon>
{
    public CouponMap()
    {
        ToTable("Coupon");
        HasRequired(c => c.Action);
    }
}

public class DiscountSchemeActionMap : EntityTypeConfiguration<DiscountSchemeAction>
{
    public DiscountSchemeActionMap()
    {
        ToTable("DiscountSchemeAction");
    }
}

public class DiscountSchemeMap : EntityTypeConfiguration<DiscountScheme>
{
    public DiscountSchemeMap()
    {
        ToTable("DiscountScheme");

        HasRequired(ds => ds.Action);
    }
}

我正在尝试进行的查询:

using(var context = new Context()/* My database context, using a custom wrapper framework*/)
{
  Console.WriteLine(context.Coupons.ToList()); // nothing
  Console.WriteLine(context.DiscountSchemes.ToList()); // the contents of the table
}

如果我查询操作 table,我确实得到了内容,但是对于 CouponAction 我没有得到连接的 Coupon,对于 DiscountScheme 它按预期工作。

问题出在你们的一对一关系上。默认情况下,EF 期望 1 对 1 在两个 table 上使用 PK。通过将 CouponID 放在 CouponAction 上,您不是在设置 1 对 1 关系,而是在设置 1-to-many/many-to-1。没有什么能阻止多个 CouponAction 记录具有相同的 CouponId。您可以对 CouponID 设置唯一约束,但如果是这种情况,那么您也可以将 CouponAction 的主键设为 CouponID。因此,这就是为什么我不建议使用 "Id" 作为 PK 名称,而是建议使用 CouponId 与 DiscountId 等

如果优惠券和操作之间的关系确实是一对一,那么去掉操作上的 CouponId table,并确保您在两者中使用相同的 ID 值 tables 的相关记录。您可以通过更改映射以将 EF 配置为在 CouponAction 上使用 CouponId 作为 PK 来对此进行测试。执行此操作后,您应该会看到相关记录。

或者,您可以建立从操作到优惠券的多对一关系 (HasOne.WithMany()),但没有 return 优惠券上没有 CouponActionId 的引用。或者您可以设置一对多,其中优惠券包含 ICollection<CouponAction> CouponActions,即使您打算每张优惠券只执行一个操作。但如果它是 1 对 1,那么我强烈建议在两个 table 中使用相同的 PK 值。