代码之家  ›  专栏  ›  技术社区  ›  RPM1984

每个层次结构的实体框架4表-如何定义子级上的导航属性?

  •  10
  • RPM1984  · 技术社区  · 15 年前

    我目前有一个实体框架4.0模型,其中包含每类型表(TPT),但存在一些性能问题(很多LOJ/CASE语句),以及两个特定域区域(多对多)之间的问题映射。

    我决定试试TPH。

    我有一个实体叫做 位置 “那是 摘要 ,以及所有其他实体的基。

    我就有了 国家 ", " 西蒂 ", " 国家 ", " 街道 “,等等,都来源于地点。

    " 位置类型 “是 二边肌 .

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

    例如,a“ 国家 “有一个” 国家 “,所以我应该能够做到:

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

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

    alt text

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

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

    我们怎么做?

    TPH也不清楚我们是否可以先对它建模,或者我们必须从DB开始,修复模型,然后重新生成DB。我还没有在网上找到一个很好的例子来说明如何定义TPH儿童的nav。

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

    编辑

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

    编辑

    这是我目前的型号:

    alt text

    当前收到的验证错误:

    错误1错误3002:映射中的问题 从第行开始的片段 359:潜在的运行时冲突 表位置键 (Locations.LocationId):列 (Locations.LocationId)映射到 实体集邻域zipcode's 属性 (邻居zipcode.neighbory.LocationId) 在概念方面,但他们没有 形成实体集的键属性 (neighboryzipcode.neighbory.LocationId, 邻居ZipCode.ZipCode.LocationId)。

    我想我会继续编辑这个问题,编辑是关于我现在在哪里。我开始怀疑是否有可能用自述FK的TPH。

    编辑

    所以我发现了上面的错误,那是因为我错过了邻域ZipCode many-to-many的连接表。

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

    但现在我发现这个错误:

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

    如果我看一下CSDL,这里是“County State”(一个州有多个县,一个县有一个州)的关联映射:

    <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 联想也是这种情况。

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

    1. ZipCode只有一个状态,由StateLocationId(Locations表)表示

    在TPH中无效吗?

    1 回复  |  直到 13 年前
        1
  •  5
  •   Community Mohan Dere    9 年前

    所以我解决了一些问题,但我遇到了麻烦。

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

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

    与此错误相关:

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

    那是因为我有一个FK,叫做“位置州”,我试图用它来建立“ZipCode州”的关系,而“城市州”的关系不起作用(仍然不知道为什么)。

    所以为了解决这个问题,我必须增加额外的栏目和FK——一个叫“ZipCode_State”,另一个叫“City_State”——显然它必须是介于导航和物理FK之间的1-1。

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

    那是我的鉴别器领域。在数据库方面,它是 不可为空 .

    我读了一些关于这个问题的文章,他们说你需要把关系从0….*改为1…..-但是我的关系已经是1…..*。

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

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

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

    我其实是在尝试那个解决方法(在我遇到它之前),但这个解决方法对我不起作用。我甚至试着把所有的关系从1..*改为0..*,但仍然没有成功。

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

    最后,使用TPH,我会得到一个非常大的表,其中有很多冗余的、可以为空的列。加入wise,效率更高。但至少在TPT中,我不需要有空的和自引用的FK。

    如果有人能解决这个问题,请告诉我。但在那之前,我坚持TPT。