Entity Framework 4 Table Per Hierarchy - 如何定义儿童的导航属性?

Posted

技术标签:

【中文标题】Entity Framework 4 Table Per Hierarchy - 如何定义儿童的导航属性?【英文标题】:Entity Framework 4 Table Per Hierarchy - How To Define Navigational Properties On Children? 【发布时间】:2010-11-24 04:47:47 【问题描述】:

我目前有一个 Entity Framework 4.0 模型和每个类型的表 (TPT),但存在一些性能问题(许多 LOJ/CASE 语句),以及两个特定领域领域之间的问题映射(许多对多)。

我决定试试 TPH。

我有一个名为“Location”的实体抽象,是所有其他实体的基础。

然后我有“Country”、“City”、“State”、“Street”,等都来自位置。

LocationType”是鉴别符

这部分工作正常,但我在尝试为派生类型定义导航属性时遇到问题。

例如,一个“State”只有一个“Country”,所以我应该可以这样做:

var state = _ctx.Locations.OfType<State>().Include("Country").First();
var countryForState = state.Country;

但这需要在“State”派生实体上具有一个名为“Country”的导航属性。我该怎么做呢?当我从数据库生成模型时,我有一个表,所有 FK 都指向同一个表中的记录:

(注意:我在数据库中手动创建了这些 FK)。

但是 FK 被放置为“Location”实体上的导航,那么我如何将这些导航属性向下移动到派生实体?我无法复制+粘贴导航,也无法“创建新的导航属性”,因为它不允许我定义开始/结束角色。

我们如何做到这一点?

TPH 也不清楚我们是否可以先做模型,或者我们必须从数据库开始,修复模型然后重新生成数据库。我还没有在互联网上找到一个很好的例子来说明如何为患有 TPH 的儿童定义导航。

注意:我不想先做代码。我当前的解决方案有 EDMX 和纯 POCO 的 TPT,我希望不影响域模型/存储库(如果可能),并且只更新 EF 模型/数据库。

编辑

仍然没有解决方案-但是我尝试先执行模型,然后执行添加-> 新关联,这实际上允许我向派生实体添加导航。但是当我尝试“从模型生成数据库”时,它仍然尝试为“Location_Street”、“Location_Country”等创建表。这几乎就像 TPH 不能先做模型一样。

编辑

这是我目前的模型:

我目前得到的验证错误:

错误 1 ​​错误 3002:映射问题 从行开始的片段 359:潜在的运行时违规 表位置的键 (Locations.LocationId):列 (Locations.LocationId) 映射到 EntitySet Neighbourhood邮政编码的 特性 (NeighbourhoodZipCode.Neighbourhood.LocationId) 在概念方面,但他们没有 形成 EntitySet 的关键属性 (NeighbourhoodZipCode.Neighbourhood.LocationId, NeighbourhoodZipCode.ZipCode.LocationId)。

只是想我会继续编辑这个问题,并编辑关于我目前所处的位置。我开始怀疑带有自引用 FK 的 TPH 是否可能。

编辑

所以我发现了上述错误,那是因为我错过了 Neighbourhood-ZipCode 多对多的连接表。

添加连接表(并将导航映射到该表)解决了上述错误。

但现在我得到了这个错误:

错误 3032:映射问题 从第 373 行开始的片段, 382:条件成员 'Locations.StateLocationId' 有 重复条件值。

如果我查看 CSDL,这里是“CountyState”的关联映射(一个州有很多县,一个县有 1 个州):

<AssociationSetMapping Name="CountyState" TypeName="Locations.CountyState" StoreEntitySet="Locations">
   <EndProperty Name="State">
      <ScalarProperty Name="LocationId" ColumnName="StateLocationId" />
   </EndProperty>
   <EndProperty Name="County">
      <ScalarProperty Name="LocationId" ColumnName="LocationId" />
   </EndProperty>
   <Condition ColumnName="StateLocationId" IsNull="false" />
</AssociationSetMapping>

Condition ColumnName="StateLocationId"在抱怨,因为ZipCodeState关联也是这种情况。

但我不明白。所有实体的鉴别器都是唯一的(我已经三重检查了),我会认为这是一个有效的场景:

    县有一个州,由 StateLocationId(位置表)表示 ZipCode 有一个州,用 StateLocationId(位置表)表示

这在 TPH 中无效吗?

【问题讨论】:

只是好奇:您是否尝试过调整数据库并坚持使用每种类型的表? @Paul Keister - 性能只是问题中的一个。我的域模型还包括“帖子”,它有一个带有“位置”的 M-M。使用 TPT,因为每个位置都有自己的表,所以很难将“帖子”映射到多个“位置”。很难解释 - 但如果我有 1 个单一的“位置”表,它会让关联更加直接。 我也刚刚尝试为 EF 抱怨的重复关系添加额外的 FK - 例如 FK_County_StateFK_ZipCode_State 而不是 FK_State 由两者共享),然后重建模型 - 仍然是完全相同的错误。不要告诉我我也必须创建额外的实际列? (现在试试) RE 我上面的评论 - 是的,我也必须创建那些实际的附加列。这解决了上述错误 - 现在我当然有下一个。 :) @Alex James - 如果您在那里,您能否告知是否有解决此问题的方法? (见我下面的答案)。否则我将不得不坚持 TPT。 【参考方案1】:

所以我解决了一些问题,但我碰壁了。

首先,当您在数据库端创建自引用 FK 时,当您尝试“从数据库更新模型”时,Entity Framework 会将这些导航属性添加到主基类型,因为它没有明确的意义TPH - 您需要在模型端执行此操作。

但是,您可以手动将导航属性添加到子类型。

WRT 这个错误:

错误 3032:从第 373、382 行开始映射片段时出现问题:条件成员“Locations.StateLocationId”具有重复的条件值。

那是因为我有一个名为“Location_State”的 FK,我试图将它用于“ZipCode_State”关系和“City_State”关系 - 这不起作用(仍然不知道为什么)。

所以为了解决这个问题,我不得不添加额外的列和额外的 FK——一个称为“ZipCode_State”,另一个称为“City_State”——显然它必须是 navs 和物理 FK 之间的 1-1。

Location.LocationType 没有默认值并且不能为空。存储实体数据需要列值。

这是我的鉴别器字段。在数据库端,它是不可为空的

我阅读了有关此问题的线程,他们说您需要将关系从 0..* 更改为 1..* - 但我的关系已经是 1..*。

如果您查看我上面的“位置”实际数据库表,所有 FK 都可以为空(它们必须是)。因此我开始怀疑我的关系是否应该是 0..*.

但由于 TPH,它们可以为空 - 并非所有“位置”都有“状态”。但是如果那个位置是一个“城市”,那么它必须有一个“州”。

这个 SO 问题进一步安慰了我的感受:ADO EF - Errors Mapping Associations between Derived Types in TPH

我实际上是在尝试这种解决方法(在我遇到它之前),但这种解决方法对我不起作用。我什至尝试将所有关系从 1..* 更改为 0..*,但仍然没有运气。

在这里浪费了太多时间,我已经回到 TPT。

在一天结束时,如果使用 TPH,我将拥有一张大得离谱的表,其中包含大量冗余、可为空的列。 JOIN-wise,它更有效。但至少对于 TPT,我不需要具有可为空和自引用的 FK。

如果有人对此问题有解决方案,请告诉我。但在那之前,我坚持使用 TPT。

【讨论】:

+1 目前,我有一些具有 TPT 继承的模型,我考虑使用 TPH 重新构建模型。现在我知道这将是浪费时间。 是的,目前我有一个包含 10 个可空 FK 的表。看起来真的很丑。 JOINS 会表现得更好吗?可能是物理意义上的,但不是逻辑意义上的。 select * from tablea inner join table b (TPT) 和 select * from tablea as one inner join tablea as two (TPH) 之间唯一真正的区别是 TPH 转到同一个表,TPT 转到另一个表。 JOIN 操作的成本是相同的(我认为)。我主要担心的是我没有看到这么多可为空的 FK 的意义

以上是关于Entity Framework 4 Table Per Hierarchy - 如何定义儿童的导航属性?的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Code-First(9.7):DataAnnotations - Table Attribute

.Net Entity Framework连接MySql

Query Using Entity Framework Error with Database Table name Error

Entity Framework 6 - ORA-00932 同时加入 ToString

Entity Framework Core 6.0 预览4 性能改进

Entity Framework 6 Code First 函数映射