Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带表拆分的EF继承_C#_Entity Framework - Fatal编程技术网

C# 带表拆分的EF继承

C# 带表拆分的EF继承,c#,entity-framework,C#,Entity Framework,我试图将两个不同的EF模型映射到同一个表SharedTable,让我们称它们为EntityA和EntityB。我让它们都扩展了一个名为BaseEntity的基本实体 EntityA仅使用SharedTable字段定义,EntityB在SharedTable和EntityBTable中有字段 modelBuilder.Entity<BaseEntity>() .Map<EntityA>(m => m.Requires("IsEn

我试图将两个不同的EF模型映射到同一个表SharedTable,让我们称它们为EntityA和EntityB。我让它们都扩展了一个名为BaseEntity的基本实体

EntityA仅使用SharedTable字段定义,EntityB在SharedTable和EntityBTable中有字段

        modelBuilder.Entity<BaseEntity>()
            .Map<EntityA>(m => m.Requires("IsEntityA").HasValue<bool>(true))
            .Map<EntityB>(m => m.Requires("IsEntityA").HasValue<false>(true));

        modelBuilder.Configurations.Add(new EntityBMap());
        modelBuilder.Configurations.Add(new EntityAMap());
        modelBuilder.Configurations.Add(new BaseEntityMap());
映射是

public class BaseEntityMap : EntityTypeConfiguration<BaseEntity>
{
    public BaseEntityMap()
    {
        // Primary Key
        this.HasKey(t => t.Id);

        this.ToTable("SharedTable");
        this.Property(t => t.Id).HasColumnName("Id");
        this.Property(t => t.SharedTableField1).HasColumnName("SharedTableField1");
    }
}

public class EntityAMap : EntityTypeConfiguration<EntityA>
{
    public EntityAMap()
    {
        this.HasKey(t => t.Id);
        this.Property(t => t.Id).HasColumnName("Id");
        this.ToTable("SharedTable");
        this.Property(t => t.SharedTableField2).HasColumnName("SharedTableField2");
    }
}

public class EntityBMap : EntityTypeConfiguration<EntityB>
{
    public EntityBMap()
    {
        Map(c =>
        {
            HasKey(t => t.Id);
            Property(t => t.Id).HasColumnName("Id");
            c.Properties(t => new
            {
                t.SharedTableField2
            });
            c.ToTable("SharedTable");
        });

        Map(c =>
        {
            c.Properties(t => new
            {
                t.EntityBTableField1
            });
            c.ToTable("EntityBTable");
        });
    }
}
公共类BaseEntityMap:EntityTypeConfiguration
{
公共BaseEntityMap()
{
//主键
this.HasKey(t=>t.Id);
本表为ToTable(“SharedTable”);
this.Property(t=>t.Id).HasColumnName(“Id”);
this.Property(t=>t.SharedTableField1).HasColumnName(“SharedTableField1”);
}
}
公共类EntityAMap:EntityTypeConfiguration
{
公共实体映射()
{
this.HasKey(t=>t.Id);
this.Property(t=>t.Id).HasColumnName(“Id”);
本表为ToTable(“SharedTable”);
this.Property(t=>t.SharedTableField2).HasColumnName(“SharedTableField2”);
}
}
公共类EntityBMap:EntityTypeConfiguration
{
公共实体bmap()
{
地图(c=>
{
HasKey(t=>t.Id);
属性(t=>t.Id);
c、 属性(t=>new
{
t、 SharedTableField2
});
c、 ToTable(“SharedTable”);
});
地图(c=>
{
c、 属性(t=>new
{
t、 EntityBTableField1
});
c、 ToTable(“实体表”);
});
}
}
我得到的错误是:

EntityFramework.dll中首次出现类型为“System.NotSupportedException”的异常

其他信息:无法按定义映射类型“EntityB”,因为它映射使用实体拆分或其他继承形式的类型的继承属性。选择不同的继承映射策略以不映射继承的属性,或者将层次结构中的所有类型更改为映射继承的属性而不使用拆分


有没有办法解决这个问题?

您选择的继承策略是

您有三种类型:一种基本类型
BaseEntity
和两种派生类型
EntityA
EntityB
。你决定把它们放在三张不同的桌子上。
EntityA
EntityB
BaseEntity
属性将放在一个表中
EntityA
EntityB
BaseEntity
表中都有其基本属性的外键

这种继承策略是否最适合您的问题取决于您主要是查询“BaseEntities that…”还是查询“EntityA that…”和“Entityb that…”

是不是使用更适合您的问题

如果您选择TPT继承策略,那么对于每个查询,“EntityA with some base class properties that…”将需要一个联接

如果您使用TPC,则不需要此连接。然而,TPC的缺点是,每当您请求“BaseEntities that…”时,两个表之间就需要Concat

因此,这取决于您最常执行的查询类型,哪种继承策略最适合您的需要

如果您想坚持战略TPT,那么您似乎没有正确构建模型

  • 您不希望任何人单独存储
    BaseEntity
    对象。如果允许的话,它不是继承,而是一对零或一个关系:每个
    EntityA
    都属于一个
    BaseEntity
    ,每个
    BaseEntity
    都有零或一个“EntityA
    。这不是您想要的:每个
    BaseEntity
    都有一个
    EntityA
    或一个'
    EntityB
    ,而每个'EntityA
    /
    EntityB
    都有一个'BaseEntity'`
  • 由于您不想在没有派生类的情况下存储
    BaseEntity
    对象,因此应该将“BaseEntity”类声明为抽象类,如给定的TPT链接中所示
  • EntityA
    en
    EntityB
    的类定义中,不要提及
    BaseEntity
    表的外键。同样,请参见TPT的给定链接
我认为抽象基类和缺少外键是关键 让实体框架知道您选择的关键信息 继承策略TPT

  • 在模型构建中,仅提及表名,必要时提及列名。别提外键
当我像这样构建您的模型时,entity framework创建了三个表,如TPT。需要任何额外的fluent API或属性。尽管我没有提到外键,但实体框架知道它们是多态关联所需要的。再次查看TPT的链接


顺便问一下,整数上的[Required]有用吗?即使我想,我也不能给这个整数一个空值。你不是指[钥匙]吗?因为您遵循的是偶数,所以这是不必要的。

为什么要将
t.EntityBTableField1
映射到另一个表?(这被称为实体拆分)。将其存储在另一个表中是有意义的,因为它不会在所有记录中使用,因此减少了不需要提取的数据量。如果实际上是关于大型对象或昂贵的计算字段,这可能是有意义的。我不会担心一些
int
s或其他小类型。您还可以使用投影(
Select(x=>new{…}
)来限制查询结果中的字段数量。感谢Gert,这是我为提问而创建的一个简化场景,但是需要移动的真实数据非常大
public class BaseEntityMap : EntityTypeConfiguration<BaseEntity>
{
    public BaseEntityMap()
    {
        // Primary Key
        this.HasKey(t => t.Id);

        this.ToTable("SharedTable");
        this.Property(t => t.Id).HasColumnName("Id");
        this.Property(t => t.SharedTableField1).HasColumnName("SharedTableField1");
    }
}

public class EntityAMap : EntityTypeConfiguration<EntityA>
{
    public EntityAMap()
    {
        this.HasKey(t => t.Id);
        this.Property(t => t.Id).HasColumnName("Id");
        this.ToTable("SharedTable");
        this.Property(t => t.SharedTableField2).HasColumnName("SharedTableField2");
    }
}

public class EntityBMap : EntityTypeConfiguration<EntityB>
{
    public EntityBMap()
    {
        Map(c =>
        {
            HasKey(t => t.Id);
            Property(t => t.Id).HasColumnName("Id");
            c.Properties(t => new
            {
                t.SharedTableField2
            });
            c.ToTable("SharedTable");
        });

        Map(c =>
        {
            c.Properties(t => new
            {
                t.EntityBTableField1
            });
            c.ToTable("EntityBTable");
        });
    }
}