gpt4 book ai didi

c# - 使用继承时复制外键

转载 作者:行者123 更新时间:2023-11-30 21:39:36 26 4
gpt4 key购买 nike

我创建了这些类,以便通过 EntityFramework 6 代码优先方法生成数据库模型:

public class Vehicle 
{
public long Id { get; set; }

public long ResponsiblePersonId { get; set; }
}

public class Car: Vehicle {

public int HorsePower { get; set; }

}

public class Bike: Vehicle {

public int FrameSize { get; set; }

}

public class Organisation
{
public Organisation()
{
Cars = new List<Car>();
Bikes = new List<Bikes>();
}

public long Id { get; set; }


public List<Car> Cars { get; set; }

public List<Bike> Bikes { get; set; }
}

到目前为止,这似乎适合我。但不幸的是,生成的表格如下所示:

Id | ResponsiblePersonId | HorsePower | FrameSize | Discriminator | Organisation_Id | Organisation_Id1

为什么 Organization ForeignKey 被生成了两次?我希望这张表只有一个 Organisation_Id 列。

谢谢

最佳答案

EF 有多种方法可以为您的继承层次结构实现物理表。默认的,也就是您正在使用的那个,称为 Table Per Hierarchy (TPH)。它只为所有派生实体使用一个表,一个 Discriminator列指定记录中包含的实体类型。 EF 还在表中为任何派生实体中包含的每个属性添加一列。

因此派生实体与Organisation之间的关系在子级别定义(CarBike 属性的列表 Organisation 实体)EF 决定为每个子实体类型创建一个单独的列 Organisation_Id ,而您不希望这样。

如何改变这个?有几种方式:

  • 不要使用 TPH。请改用 TPC(每个具体类的表)。也就是说,EF 为您的每个子实体创建一个单独的表。如何做到这一点:删除 DbSet<Vehicle>来自您的属性(property) DbContext .如果这不行,请为从 Vehicle 派生的每个实体的物理表名称设置显式配置。像这样:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    ...
    modelBuilder.Entity<Car>().ToTable("Cars");
    modelBuilder.Entity<Bike>().ToTable("Bikes");
    }
  • 如果您需要继续使用 TPH,我不知道有什么方法可以只生成一个 OrganisationId 来实现它数据库中的列和 Vehicle 之间只有一个外键和 Organisation .常识会说您可以定义 Organisation Vehicle 处的外键基本实体级别。但是在生成迁移时你会遇到错误:

    Organisation: FromRole: NavigationProperty 'Organisation' is not valid. Type 'Car' of FromRole 'Organisation_Cars_Target' in AssociationType 'Organisation_Cars' must exactly match with the type 'Vehicle' on which this NavigationProperty is declared on.

    似乎当在基本级别定义关系时,EF 需要 Organisation 中的列表被定义为 Vehicle 类型而不是 CarBike .这不适合您的模型。

    如果您尝试定义 OrganisationIdOrganisation派生类中的属性,那么在生成迁移时会出现不同的错误,因为不允许对不同子实体中的属性使用相同的名称。您可以使用不同的名称,但您会再次获得两列。也无法通过这种方式获得一列。

    因此,如果您坚持使用 TPH,据我所知,您必须忍受为您的 OrganisationId 设置两列的情况。 .至少你可以通过一些流畅的配置以更详细的方式命名它们:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    ...
    modelBuilder.Entity<Organisation>()
    .HasMany(o => o.Bikes)
    .WithRequired()
    .Map(x => x.MapKey("OrganisationIdBike"));

    modelBuilder.Entity<Organisation>()
    .HasMany(o => o.Cars)
    .WithRequired()
    .Map(x => x.MapKey("OrganisationIdCar"));
    }

我会建议您更改为 TPC,因为对于您的模型,流畅的映射编写起来不那么复杂。

为了更好地理解 TPH、TPC 和 TPT(每个类型的表,继承层次结构的另一种实现),请阅读 this post .

关于c# - 使用继承时复制外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45107363/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com