流畅的API EF继承和映射

top*_*ess 6 c# inheritance entity-framework fluent

我有一个系统,有几个自引用实体,具有一对多的关系(父子).我想为所有这些实体使用公共基类:

public class SelfReferencing
{
  public SelfReferencing Parent {get; set;}
  public ICollection<SelfReferencing> Children {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

并从SelfReferencing继承特定实体.在尝试执行以下操作时,Fluent API映射要求引用属性为定义类型:

modelBuilder.Entity<ConcreteSelfReferencing>()
                .HasMany(e => e.Children)
                .WithOptional(e => e.Parent);
Run Code Online (Sandbox Code Playgroud)

那么,你能帮助我找到利用继承并获取实体映射的可能性吗?

谢谢

Dom*_*icz 4

注意:下面的示例称为“每个层次结构表”(TPH) - 即全部包含在一个表中。单击此链接查看每个类型的表 (TPT),其中每种类型都有不同的表。

当使用基类型和继承类型时,您必须告诉 EF 如何确定特定继承类型的关联。

获取你的代码:

public abstract class SelfReferencing
{
    public SelfReferencing Parent { get; set; }
    public ICollection<SelfReferencing> Children { get; set; }
}

public class ConcreteSelfReferencing : SelfReferencing
{
}
Run Code Online (Sandbox Code Playgroud)

EF 现在必须确定该子类是 a 子类ConcreteSelfReferencing还是任何其他类型的子类。这是由表本身的鉴别器决定的,该列不是映射的一部分。

再举一个例子,类似于我过去使用过的:

public abstract class Policy
{
   public int Id { get; set; }
   public string PolicyNumber { get; set; }
}

public class InsurancePolicy : Policy
{
}

public class CarPolicy : Policy
{
}
Run Code Online (Sandbox Code Playgroud)

该表的结构如下:

| Id    |   PolicyNumber  | Type  |  ..... |
  1         CAR0001         C
  2         ISN0001         I
Run Code Online (Sandbox Code Playgroud)

要让 EF 正确得出结果,您需要:

public class MyContext : DbContext
{
   public MyContext() : base()
   {
   }

   public DbSet<Policy> Policies { get; set; }

   protected override void OnModelCreating(ModelBuilder builder)
   {
      var policyMap = modelBuilder.Entity<Policy>();

      // Set up discriminators
      policyMap.Map<InsurancePolicy>(p => o.Requires("Type").HasValue("I"))
               .Map<CarPolicy>(p => o.Requires("Type").HasValue("C"));

      // Notice that `Type` is only used for the discriminators, not an actual
      // mapped property
      policyMap.HasKey(x=>x.Id);
      policyMap.Property(x=>x.PolicyNumber);
   }
}
Run Code Online (Sandbox Code Playgroud)

从您的代码中,您可以自己进行过滤,也可以将过滤放在DbContext. 这是来自一个单独的类的示例。

public class PolicyRepository
{
   private MyContext context = new MyContext();

   public PolicyRepository()
   {
   }

   public IQueryable<InsurancePolicy> GetInsurancePolicies()
   {
      return this.context.Policies.OfType<InsurancePolicy>();
   }

   public IQueryable<CarPolicy> GetCarPolicies()
   {
      return this.context.Policies.OfType<CarPolicy>();
   }
}
Run Code Online (Sandbox Code Playgroud)