【问题标题】:Foreign key with OR logic具有 OR 逻辑的外键
【发布时间】:2018-03-13 11:48:19
【问题描述】:

我有这样的 CodeFirst 设计:

public class Email
{
    public string Address { get; set; }

    public Company Company { get; set; }
    public int? CompanyId { get; set; }

    public User User { get; set; }
    public int? UserId { get; set; }

    //many other props
}

public class Company
{
    public List<Email> Emails { get; set; }
}

public class User
{
    public List<Email> Emails { get; set; }
}

在一个好的方面,Email 可以属于只有一个外键:CompanyId 或 UserId。但现在它允许 CompanyId 和 UserId。这是不对的。无论如何,带有可空值的设计是丑陋的。例如,要获取链接到我需要的公司的所有电子邮件,请执行以下操作:

var companyEmails = _context.Emails.Where(x => x.CompanyId.HasValue);

我觉得有一种更好的方法可以用 OR 逻辑定义乘法外键。请帮我想办法。

【问题讨论】:

    标签: entity-framework database-design orm ef-code-first


    【解决方案1】:

    如果您只想拥有一个对CompanyUser 的引用,这意味着它不会是FK,而且您应该有额外的带有描述的字段,该字段指向哪个表。

    或者,您可以尝试 Table per Hierarchy 方法。在这种情况下,数据库表几乎保持不变,只会隐式添加新的Discriminator 列,以区分类,但您可以编写更多“优雅”代码:

    public abstract class Email
    {
         public string Address { get; set; }
    }
    
    public class CompanyEmail : Email
    {
        public Company Company { get; set; }
        public int? CompanyId { get; set; }
    }
    
    public class UserEmail : BaseEmail
    {
        public User User { get; set; }
        public int? UserId { get; set; }
    }
    

    用法:

    var companyEmails = _context.Emails.OfType<CompanyEmail>();
    //underlying query:
    //select * from dbo.Emails where Discriminator = 'CompanyEmail'
    

    【讨论】:

    猜你喜欢
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2017-08-05
    • 1970-01-01
    相关资源
    最近更新 更多