【问题标题】:One-To-One relationship with FK distinct from PK与 FK 的一对一关系不同于 PK
【发布时间】:2018-07-18 16:16:04
【问题描述】:

我在数据库中有 2 个表:ReceivedGoodsReceivedGoodsProperties ReceivedGoods 包含 ReceivingId 作为 PK 并且必须在 ReceivedGoodsProperties 中包含其扩展数据,其中包含 ReceivingId 作为 FK 引用 ReceivedGoodsReceivingId。然而,当前ReceivedGoodsProperties 有自己的 PK Id,因此与 FK 不同。所以我有以下几点:

public class ReceivedGoods
{
    ...
    public int ReceivingId { get; set; }
    ...
    public virtual ReceivedGoodsProperties properties { get; set; }
}

public class ReceivedGoodsProperties
{
    ...
    public int Id { get; set; } // This is PK
    public int ReceivingId { get; set; } // This is FK
    ...
    public virtual ReceivedGoods goods { get; set; }
}

我想获取ReceivedGoods 对象并自动加载属性,但我不知道如何在 EF 中设置它。 我尝试过这样的事情(来自ReceivedGoodsProperties 侧映射):

this.HasRequired(p => p.goods)
    .WithRequiredDependent(d => d.properties)
    .Map(m => m.MapKey("ReceivingId"));

但我最终会遇到以下错误:

ReceivingId: Name: Each property name in a type must be unique. Property 
name 'ReceivingId' is already defined.

ReceivedGoodsProperties 中注释掉ReceivingId 时,不抛出上异常,ReceivedGoods 被正确加载,除了properties 属性。

谁能解释一下,在这种情况下如何进行一对一的映射?

【问题讨论】:

  • 就我个人而言,我会让 FK 成为 PK。是否有理由需要单独的 PK?我能想到的唯一原因是,如果您想要一对零或一对关系,那么您的 FK 需要可以为空。
  • 不幸的是我已经设计好了数据库。 1 到 0 或 1 不是我的情况,但我不确定现在是否可以更改 PK。

标签: c# entity-framework-6 one-to-one ef-fluent-api


【解决方案1】:

你可以试试:

public class ReceivedGoods
{
    ...
    public int ReceivingId { get; set; }
    ...
    public virtual ReceivedGoodsProperties properties { get; set; }
}

public class ReceivedGoodsProperties
{
    ...
    public int Id { get; set; } // This is PK
    [ForeignKey( "goods " )]
    public int ReceivingId { get; set; } // This is FK
    ...
    [Required]
    public virtual ReceivedGoods goods { get; set; }
}

顺便说一句,在 C# 中,标准指南是针对 PascalCase 成员的,所以 GoodsProperties

【讨论】:

    【解决方案2】:

    尝试以这种方式定义关系:

    this.HasRequired(p => p.goods)
        .WithRequiredDependent(p => p.properties)
        .HasForeignKey(p => p.ReceivingId);
    

    如果您遵循标准的 EF 命名约定,它通常可以自己找出这些关系。只有当您的导航属性名称与类名称不对应时,或者您有多个 FK 到源表中的同一目标时,您才会真正遇到麻烦。

    如果您希望“自动”填写导航属性,请在查询中使用Include 扩展方法,如:context.Goods.Include(g=>g.properties)。除非您想使用延迟加载,否则您不必将它们声明为 virtual

    你可能需要从其他实体来:

    this.HasRequired(p => p.properties)
        .WithRequiredPrincipal(p => p.goods)
        .HasForeignKey(p => p.ReceivingId);
    

    【讨论】:

    • 不将它们标记为virtual 并不意味着它会急切地加载它们,它只是意味着它永远不会延迟加载它们,因为代理将无法覆盖它。但如果你想急切加载,你仍然需要.Include()
    • 不幸的是,HasForeignKey() 在提议的链接中不可用。只有 map() 和 WillCascadeOnDelete() 会弹出。
    • 嗯.. 尝试从其他实体配置它,并改用WithRequiredPrincipal;那应该给你HasForeignKey选项。
    • @BradleyUffner 仍然没有运气......只是按照您的建议尝试从 ReceivedGoods 一侧配置它,但 HasForeignKey() 不可用。
    猜你喜欢
    • 2017-07-25
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多