【问题标题】:In Entity Framework, how can I create a referrential constraint using a subset of the primary key?在实体框架中,如何使用主键的子集创建引用约束?
【发布时间】:2009-06-17 20:09:29
【问题描述】:

我的数据模型包含两个具有复合主键的表和一个关联表。部分复合主键在表之间是通用的。

SitePrivilege
-------------
SiteId
PrivilegeId

UserSite
--------
SiteId
UserId

UserSitePrivilege
-----------------
UserId
SiteId
PrivilegeId

我创建了一个 SitePrivilege 实体和一个 UserSite 实体。我已将它们之间的多对多关联映射到 UserSitePrivilege。

<Association Name="UserSiteSitePrivilege">
  <End Type="PrivilegeModel.UserSite" Multiplicity="*" Role="UserSite" />
  <End Type="PrivilegeModel.SitePrivilege" Multiplicity="*" Role="SitePrivilege" />
</Association>
...
<AssociationSetMapping Name="UserSiteSitePrivilege" TypeName="PrivilegeModel.UserSiteSitePrivilege" StoreEntitySet="UserSitePrivilege">
  <EndProperty Name="SitePrivilege">
    <ScalarProperty Name="PrivilegeId" ColumnName="PrivilegeId" />
    <ScalarProperty Name="SiteId" ColumnName="SiteId" />
  </EndProperty>
  <EndProperty Name="UserSite">
    <ScalarProperty Name="SiteId" ColumnName="SiteId" />
    <ScalarProperty Name="UserId" ColumnName="UserId" />
  </EndProperty>
</AssociationSetMapping>

上面的代码产生了这个错误:

表中以下列中的每一列 UserSitePrivilege 映射到 多个概念方面的属性: UserSitePrivilege.SiteId 映射到 UserSiteSitePrivilegeSitePrivilege.SiteId, UserSiteSitePrivilege.UserSite.SiteId

所以我添加了一个引用约束。

<Association Name="UserSiteSitePrivilege">
  <End Type="PrivilegeModel.UserSite" Multiplicity="*" Role="UserSite" />
  <End Type="PrivilegeModel.SitePrivilege" Multiplicity="*" Role="SitePrivilege" />
  <ReferentialConstraint>
    <Principal Role="UserSite">
      <PropertyRef Name="SiteId"/>
    </Principal>
    <Dependent Role="SitePrivilege">
      <PropertyRef Name="SiteId"/>
    </Dependent>
  </ReferentialConstraint>
</Association>
...
<AssociationSetMapping Name="UserSiteSitePrivilege" TypeName="PrivilegeModel.UserSiteSitePrivilege" StoreEntitySet="UserSitePrivilege">
  <EndProperty Name="SitePrivilege">
    <ScalarProperty Name="PrivilegeId" ColumnName="PrivilegeId" />
    <ScalarProperty Name="SiteId" ColumnName="SiteId" />
  </EndProperty>
  <EndProperty Name="UserSite">
    <ScalarProperty Name="SiteId" ColumnName="SiteId" />
    <ScalarProperty Name="UserId" ColumnName="UserId" />
  </EndProperty>
</AssociationSetMapping>

现在它会产生这个错误:

委托人推荐的物业 角色 UserSite 必须是 与 EntityType 的键相同 PrivilegeModel.UserSite 所引用的 关系中的主要角色 关系约束 PrivilegeModel.UserSiteSitePrivilege。 确保所有关键属性 在 Principal Role 中指定。

如何正确建模这种关系?

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    3.5 SP1 不支持这样的重叠 FK。

    UserSitePrivilege
    ----------
    UserId 
    SiteId
    PrivilegeId
    
    PK => UserId, SitedId, PrivilegeId
    FK1 => UserId, SiteId
    FK2 => SiteId, PrivilegeId
    

    FK1 与 FK2 重叠。这将在 EF 4 的 Beta2 中得到支持。这是因为 FK 关联(在 Beta2 中可用)比独立关联(在 3.5 SP1 和 4.0 Beta 1 中拥有的)灵活得多。

    有关FK Associations的更多信息,请参阅此帖子

    与此同时,您唯一的选择可能是将所有这些隐藏在 DefiningQueries 和 CUD 过程等后面。

    • 亚历克斯

    【讨论】:

      【解决方案2】:

      如果您的主键是复合键,那么您的所有外键关系也必须使用整个复合键(所有键列)作为参考——我看不出有什么办法可以解决这个问题,这是一个基本原则关系数据库设计,真的。

      这绝对是我可能会选择在主表上使用替代列作为主键的主要原因之一,而不是由实际数据列组成的复合键。

      更新: 是的,根据您的评论,您是绝对正确的 - 数据库设计是可靠的。不太清楚为什么 EF 不能处理这个....

      马克

      【讨论】:

      • 整个复合键都在外键中使用。 UserSitePrivilege 有两个复合外键:(UserId, SiteId) 和 (SiteId, PrivilegeId)。但是因为它是一个关联表,所以它没有被表示为一个实体。任一表上的代理主键都可以解决问题,但我希望我不必为了满足 EF 而要求 DBA 更改 DB 设计。他的设计是有效的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多