首页 > 解决方案 > EF 核心具有相同外键的多个虚拟属性

问题描述

在实体框架中是否可以对几个 realted 属性使用相同的外键。例如:

// There is one table for credit cards. To destinguish between company credit cards and lets say shoppers credit cards there is tag field CustomerType. SO two different credit cards can have the smae EntityId but if CustomerType is different the navigatin property would point to either Client or Company table.
public enum CustomerType
{
   Client,
   Company
}

public class Client
{
   public int Id { get; set; }
   virtual public IEnumerable<CreditCard> CreditCards { get; set; }  
}
public class Company
{
    public int Id { get; set; }
    virtual public IEnumerable<CreditCard> CreditCards { get; set; }  
}

public class CreditCard
{
   public int Id { get; set; }
   //this points to either company or client depending on the customertype field.
   public int EntityId { get; set; }
   public CustomerType Type { get;set;}
   public virtual Client Client { get; set; }
   public virtual Company Company { get; set; }
}
 ......
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   // obviously this is wrong ...
   modelBuilder.Entity<Client>(entity =>
   {
       entity.HasMany(x => x.CreditCards)
           .WithOne(y => y.Client)
           .HasForeignKey(z => z.HolderId);
   });

   modelBuilder.Entity<Company>(entity =>
   {
      entity.HasMany(x => x.CreditCards)
          .WithOne(y => y.Company)
          .HasForeignKey(z => z.HolderId);
   });
 }

或者我应该忘记它并将公司信用卡和客户信用卡放在不同的表中。那将是直截了当的。

标签: entity-frameworkentity

解决方案


该模型打破了规范化。如果公司与客户信用卡有单独的表,则从表结构中可以看出,实体也应声明公司与客户信用卡。将您建议的表结构中的 Table-per-Concrete 继承与您似乎想要在实体中设置的 Table-per-Hierarchy 混淆。通常最好让您的实体反映您的数据结构。

EF 可以通过继承处理这种情况:

public abstract class CreditCard
{
    [Key]
    public int Id { get; set; }
    // card details
}

public class ClientCreditCard : CreditCard
{
    public virtual Client Client { get; set; }
}

public class CompanyCreditCard : CreditCard
{
    public virtual Company Company { get; set; }
}

Company 将拥有一组 CompanyCreditCards,而 Clients 将拥有 ClientCreditCards。

从表的角度来看,您可以有一个带有信用卡类型鉴别器的 CreditCard 表,尽管公司或客户的 ID 都可以为空。(Table-Per-Hierarchy) 来维护与其他实体的 FK 关系。有一个鉴别器+“EntityId”,它指向或者破坏规范化。(没有 FK 可能)


推荐阅读