【问题标题】:EF, How to conditionally include a navigation property that type of it related to value of another property?EF,如何有条件地包含一个导航属性,它的类型与另一个属性的值相关?
【发布时间】:2021-01-06 05:24:18
【问题描述】:

我有以下实体:

public class Notification
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Guid RefId { get; set; }
    public Object Ref { get; set; } //  << The navigation property: Sometime its type is Poll and sometime is Test, maybe I add other types too 
    public NotifTypes Type { get; set; }
}

public enum NotifTypes
{
    Poll=1,
    Test=2,
    // Other NotifTypes here
}

//-------------------------------------------------------------------

public class Test
{
    public int Id { get; set; }
    public string Title { get; set; }

    public IEnumerable<Notification> { get; set; }
}

public class Poll
{
    public int Id { get; set; }
    public string Answer1 { get; set; }
    public string Answer2 { get; set; }

    public IEnumerable<Notification> { get; set; }
}

好的,

  • Notification 对象的Type 属性等于Poll 时,RefId 将由PollId 填充
  • 当类型等于Test 时,refId 将由TestId 填充。

现在我想有条件地将相关的PollTest 包含在Ref 属性中。我应该如何实现它?

我想防止添加单独的 ID,如 PollIdTestId 和.... 到 Notification,因为我确信每次只有其中一个具有价值,所以我想要一个 RefId和一个 Ref 属性而不是它们。

【问题讨论】:

  • 这不是一个好的设计,我很确定你无法让它与 EF 一起使用。您应该有一个单独的实体(Notification 指向的实体),其中包含指向相关表格的链接。
  • 只有PollTest 具有共同的基本类型并通过数据库继承(例如TPH 或TPT)映射到数据库时才有效,此外,您的NotifTypes 枚举有问题
  • @AluanHaddad 你可以解释一下你在评论中写的答案的实现吗?
  • 我的意思是class Notification { public string Title { get; set; } public int Id { get; set; } } 然后是class PollNotification: Notification { public Poll Poll { get; set;} }class TestNotification: Notification { public Test Test { get; set; } }class Poll { public ICollection&lt;PollNotification&gt; Notifications { get; set; } = new (); } 等等。然后删除NotifTypes
  • 如果是直接查询通知,可以写from pn db.Notifications.OfType&lt;PollNotification&gt;() where pn.Poll.Answer1 == "Biden or Trump" select pn;

标签: c# entity-framework code-first


【解决方案1】:

我不知道 EntityFramework,但你让我回答这个问题。

您基本上是在重新发明,这不是一个好的关系设计。您可以阅读我过去对这个概念的一些回答:

我倾向于回答 MySQL 问题,但对于任何其他品牌的 RDBMS,答案都是一样的。您不能声明引用多个表的实际外键约束这一事实应该表明这种设计是不正确的。

从数据建模的角度来看,最简单的解决方案是为每个潜在的表引用创建一个独立的属性。在给定的行上,除了其中一个之外,所有这些都将为 NULL。

我不知道 EntityFramework 如何支持这一点。 @AluanHaddad 的建议听起来不错。

尽量不要破坏关系概念。沿着这条路走就是Inner-Platform Effect antipattern

【讨论】:

  • 感谢比尔 4 的干净回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多