Dans Entity Framework, comment créer une contrainte référentielle en utilisant un sous-ensemble de la clé primaire?

entity-framework

Question

Mon modèle de données contient deux tables avec des clés primaires composites et une table associative. Une partie de la clé primaire composite est commune aux tables.

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

UserSite
--------
SiteId
UserId

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

J'ai créé une entité SitePrivilege et une entité UserSite. J'ai mappé une association plusieurs-à-plusieurs entre eux et 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>

Le code ci-dessus produit cette erreur:

Chacune des colonnes suivantes de la table UserSitePrivilege est mappée à plusieurs propriétés conceptuelles: UserSitePrivilege.SiteId est mappé à UserSiteSitePrivilegeSitePrivilege.SiteId, UserSiteSitePrivilege.UserSite.SiteId

J'ai donc ajouté une contrainte référentielle.

<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>

Maintenant, il produit cette erreur:

Propriétés référencées par le rôle principal UserSite doit être exactement identique à la clé de EntityType PrivilegeModel.UserSite référencée par le rôle principal dans la contrainte de relation pour Relationship PrivilegeModel.UserSiteSitePrivilege. Assurez-vous que toutes les propriétés de clé sont spécifiées dans le rôle principal.

Comment modéliser correctement cette relation?

Réponse acceptée

Les FK qui se chevauchent comme celui-ci ne sont pas pris en charge dans 3.5 SP1.

c'est à dire

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

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

FK1 chevauche FK2. Cela sera pris en charge à partir de la version bêta2 de EF 4. Cela est dû au fait que les associations FK (disponibles dans la version bêta2) sont beaucoup plus flexibles que les associations indépendantes (comme dans les versions 3.5 SP1 et 4.0 Beta 1).

Voir cet article pour plus d'informations sur les associations FK

En attendant, votre seule option est probablement de cacher tout cela derrière DefiningQueries et les procédures CUD, etc.

  • Alex

Réponse populaire

Si votre clé primaire est une clé composée, toutes vos relations de clé étrangère doivent également utiliser la clé composée entière (toutes les colonnes de clé) comme référence - je ne vois aucun moyen de contourner ce problème, il s'agit d'un principe de base de la base de données relationnelle. le design, vraiment.

C’est certainement l’une des principales raisons pour lesquelles je choisirais probablement d’utiliser une colonne de substitution dans la table principale pour la clé primaire, au lieu d’une clé composée constituée de colonnes de données réelles.

UPDATE: oui, sur la base de votre commentaire, vous avez absolument raison: la conception de la base de données est solide. Pas tout à fait sûr pourquoi EF ne peut pas gérer cela ....

Marc



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow