EF Core 配置泛型类型的对象

问题描述 投票:0回答:2

我有以下对象:

public class Foo<TEntity>
{
   public int Id {get; set;}

   public ICollection<TEntity> Tasks {get; set;}
}

上述实体的类型配置为:

public abstract class FooConfig<TEntity> : IEntityTypeConfiguration<Foo<TEntity>>
{
   public virtual void Configure(EntityTypeBuilder<Foo<TEntity>> builder)
   {
      builder.ToTable("foo")

      builder.HasKey(x => x.Id);
   }
}

我有 2 个使用抽象类的 DbSet(Bar 和 Spam 与 Foo 具有多对一关系):

DbSet <Foo<Bar>> BarFoo    
DbSet <Foo<Spam>> SpamFoo

他们的配置是:

public class Bar
{
   public int Id { get; set; }
   public Foo<Bar> Foo { get; set; }
}

public class BarFooConfig : FooConfig<Bar>
{
   public override void Configure(EntityTypeBuilder<Foo<Bar>> builder)
   {
      base.Configure(builder);

      builder.HasMany(x => x.Tasks)
         .WithOne(x => x.Foo)
         .HasForeignKey(x => x.FooId)
   }
}

public class Spam
{
   public int Id { get; set; }
   public Foo<Spam> Foo { get; set; }
}

public class SpamFooConfig : FooConfig<Spam>
{
   public override void Configure(EntityTypeBuilder<Foo<Spam>> builder)
   {
      base.Configure(builder);

      builder.HasMany(x => x.Tasks)
         .WithOne(x => x.Foo)
         .HasForeignKey(x => x.FooId)
   }
}

但是当我运行代码时出现以下错误:

不能将表“Foo”用于实体类型“Foo”,因为它用于实体类型“Foo”并且它们的主键之间没有关系

如果需要更多详细信息,请告诉我

c# entity-framework-core
2个回答
0
投票

如果您不关心单个

Foo
是否可以同时拥有
Bar
Spam
子记录,那么简单的答案就是删除泛型并定义两个导航。

public class Foo
{
   public int Id {get; set;}

   public ICollection<Spam> Spam {get; set;}
   public ICollection<Bar> Bar {get; set;}
}

否则,您需要定义一个 table-per-heirachy,向 foo 表添加一个鉴别器 [shadow] 属性。

public abstract class Foo{
   public int Id {get; set;}
}

public class Foo<TEntity> : Foo{
   public ICollection<TEntity> Tasks {get; set;}
}

那么示例的其余部分可能无需任何进一步的显式配置即可运行。因为 EF Core 将发现模型其余部分中使用和配置的每个

Foo<T>

然后,每当您查询导航属性时,EF Core 都会向 sql join 子句添加鉴别器测试。

尽管您可以按照有关如何显式定义鉴别器的文档,而不是依赖 EF Core 来定义影子属性。


0
投票

我通过这样的研究得到了结果。

定义 IGenericConfiguration:

public interface IGenericConfiguration<T> : IEntityTypeConfiguration<T> where T : class
    {
        public void SpecialConfigure(EntityTypeBuilder<T> builder); 
    } 

在此输入代码

并定义通用配置:

 public abstract class GenericConfiguration<T> : IGenericConfiguration<T> where T : BaseEntitiy
 {
     public void Configure(EntityTypeBuilder<T> builder)
     {

         builder.Property(x => x.lastModifiedDate).HasColumnType("timestamp");
         builder.Property(x => x.createDate).HasColumnType("timestamp");

         SpecialConfigure(builder);
          
     }

     public virtual void SpecialConfigure(EntityTypeBuilder<T> builder) { }
 }

可以在GenericConfiguration的Config功能下进行各部分通用的conf设置

特定于实体的配置可以定义如下:

  public class TestConfiguration : GenericConfiguration<Test>  
    {
        public override void SpecialConfigure(EntityTypeBuilder<Test> builder)
        {
            builder.Property(x => x.test).HasColumnType("VARCHAR(100)");
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.