使用继承时出现重复的外键

2024-04-02

我创建了这些类,以便通过 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_Id 列。

Thanks


EF 有多种方法来实现继承层次结构的物理表。默认的(您正在使用的)称为“每层次结构表”(TPH)。它仅使用一张表来存储所有派生实体,其中一个Discriminator列来指定记录中包含的实体的类型。 EF 还在表中为任何派生实体中包含的每个属性添加一列。

因此,派生实体和Organisation是在子级别定义的(列表Car and Bike属性在Organisation实体)EF 决定为每个子实体类型创建一个单独的列Organisation_Id,而你不希望这样。

如何改变这个?有以下几种方法:

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

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

    组织:FromRole:NavigationProperty“组织”不是 有效的。在 FromRole 'Organization_Cars_Target' 中输入 'Car' AssociationType“Organization_Cars”必须与类型完全匹配 声明此 NavigationProperty 的“车辆”。

    似乎当关系在基础级别定义时,EF 期望列表在Organisation被定义为类型Vehicle并不是Car or Bike。这不适合你的模型。

    如果你尝试定义OrganisationId or Organisation派生类中的属性,然后在生成迁移时会出现不同的错误,因为不允许对不同子实体中的属性使用相同的名称。您可以使用不同的名称,但随后您会再次获得两列。也没有办法以这种方式获得一列。

    因此,如果您坚持使用 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(每个类型的表,继承层次结构的另一种实现),请阅读这个帖子 https://blogs.msdn.microsoft.com/alexj/2009/04/14/tip-12-how-to-choose-an-inheritance-strategy/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用继承时出现重复的外键 的相关文章

随机推荐

  • vi 退出后如何恢复终端内容?

    像 vi 或 man 或任何其他程序这样的程序如何用程序自己的内容替换终端内容 然后在退出这些程序后它们会带回旧的终端内容 Vi 翻转到终端支持的备用屏幕缓冲区 这是通过使用转义序列来实现的 看这个链接 http invisible isl
  • 从链表中删除最小值[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我需要从链表中删除最小的元素值 喜欢
  • 在地图周围绘制各州省份,并用德国邮政编码着色

    我正在尝试创建一张地图 在其中按德国邮政编码进行着色 并且我想添加德国各州作为边界 for loading our data library raster library readr library readxl library sf li
  • 如何从 GAC 加载程序集?

    我正在尝试使用 Assembly Load 加载 GAC 中的程序集 例如 假设我想列出存在于的所有类型演示核心 dll 我该如何加载演示核心 dll 当我尝试这个时 Assembly a Assembly Load Presentatio
  • MUI:如何以编程方式删除 DataGrid 中选定的行?

    我正在使用 MUI 创建文件列表DataGrid 用户可以选中复选框DataGrid做出他们的选择 我希望在用户执行某些操作 例如删除所选文件 后重置该复选框 我面临的问题是在执行删除操作后 该复选框仍然在同一位置被选中 例如 在我按下删除
  • 更改搜索栏拇指的大小

    我正在使用可绘制的搜索栏拇指 android thumb drawable thumb 我怎样才能设置这个拇指的大小dip单元 因为我使用类似搜索栏的样式 我想要拇指12dip高度和宽度 对我来说设置拇指大小的最灵
  • org.springframework.beans.factory.BeanCreationException:创建类路径资源中定义的名称为“scriptDataSourceInitializer”的bean时出错?

    我是学习 Spring Boot Web 的新手 我已经开始学习 spring jpa 数据 我使用 h2 数据库 我想使用插入测试数据 org springframework beans factory BeanCreationExcep
  • 仅显示 SQL 查询的前 N ​​行输出

    有没有办法只显示前 N 行输出SQL query 如果查询停止运行一次 则奖励积分N输出行 我最感兴趣的是找到适用于的东西Oracle 如果您指定您的目标数据库将会很有帮助 不同的数据库有不同的语法和技术来实现这一点 例如 在 Oracle
  • Git:如何排除存储库中的子文件夹?

    我已经在我的项目的文件夹中创建了一个存储库 你知道 git init 我有Webstorm文件夹 idea另一个与此无关的文件夹 我对保留在存储库中不感兴趣 并且我不希望此文件夹显示为要添加的新文件 我想忘记这些子文件夹 如何在提交整个存储
  • vertx 内的多线程

    我是 vert x 的新手 我正在尝试 vert x NetServer 功能 http vertx io core manual java html writing tcp servers and clients http vertx i
  • 下载 Fuchsia 源代码 - Jiri 钩子由于更新项目或包时出现致命错误而未运行

    Per 获取紫红色源代码 https fuchsia dev fuchsia src development source code echo PATH media cwh 32GB swdev fuchsia jiri root bin
  • 如何在 SQLite 中拥有自动时间戳?

    我有一个 SQLite 数据库版本 3 我正在使用 C 创建一个使用该数据库的应用程序 我想在表中使用时间戳字段来实现并发 但我注意到当我插入新记录时 该字段未设置 并且为空 例如 在 MS SQL Server 中 如果我使用时间戳字段
  • OpenCV 使用 k 均值对图像进行色调分离

    我想在 C 接口 cv 命名空间 中使用 k means 和 OpenCV 对图像进行色调分离 但得到了奇怪的结果 我需要它来减少一些噪音 这是我的代码 include cv h include highgui h using namesp
  • 在 AngularJS 中下载 zip 文件

    尝试在 AngularJS 中下载 zip 文件 我查看了AngularJS 从服务器下载pdf文件 https stackoverflow com questions 25490007 angularjs download pdf fil
  • 按时间间隔分组

    我需要将我的表分组为 15 分钟的间隔 我可以这样做 select dateadd minute datediff minute 0 ts 15 15 0 sum goodpieces from StationCount Group by
  • 在mongodb中查找按距离排序的LineString附近的点

    我有一组代表街道 黑线 的点和代表地图上某个地点的点 红点 我想找到指定街道附近的所有点 按距离排序 我还需要能够指定最大距离 蓝色和绿色区域 这是一个简单的例子 我想用 near运算符 但它只接受Point作为输入 而不是LineStri
  • 如何确定您是否使用不带 $_SERVER['HTTPS'] 的 HTTPS

    我在网上看到很多教程说你需要检查 SERVER HTTPS 如果服务器连接受 HTTPS 保护 我的问题是在我使用的一些服务器上 SERVER HTTPS 是一个未定义的变量 会导致错误 我可以检查是否还有另一个应该始终定义的变量 需要明确
  • NSExtensionRequestHandling 不处理本机消息

    我正在尝试为我的本机应用程序创建 Safari Web 扩展 我想要一个带有按钮的弹出窗口 单击该按钮将与我的本机应用程序进行通信 在开始这部分之前 我在发送本机消息并在其中处理它时遇到了问题beginRequest类中的函数符合NSExt
  • 如何确定 UIWebView 的内容大小?

    我有一个UIWebView具有不同的 单页 内容 我想了解一下CGSize内容以适当调整我的父母视图的大小 显而易见的 sizeThatFits 不幸的是只返回 webView 的当前帧大小 事实证明 我的第一个猜测是使用 sizeThat
  • 使用继承时出现重复的外键

    我创建了这些类 以便通过 EntityFramework 6 代码优先方法生成数据库模型 public class Vehicle public long Id get set public long ResponsiblePersonId