Моя модель данных содержит две таблицы с составными первичными ключами и ассоциативную таблицу. Часть составного первичного ключа является общей для таблиц.
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>
Теперь он выдает эту ошибку:
Свойства, на которые ссылается основной пользовательский сайт роли, должны быть точно идентичны ключу EntityType PrivilegeModel.UserSite, на который ссылается основная роль в ограничении отношений для отношения отношений PrivilegeModel.UserSiteSitePrivilege. Убедитесь, что все ключевые свойства указаны в главной роли.
Как правильно моделировать эти отношения?
Перекрывающиеся FK, подобные этому, не поддерживаются в 3.5 SP1.
т.е.
UserSitePrivilege
----------
UserId
SiteId
PrivilegeId
PK => UserId, SitedId, PrivilegeId
FK1 => UserId, SiteId
FK2 => SiteId, PrivilegeId
FK1 перекрывается с FK2. Это будет поддерживаться начиная с бета-версии 2 EF 4. Это связано с тем, что ассоциации FK (которые доступны в бета-версии 2) гораздо более гибкие, чем независимые ассоциации (то, что имеется в 3.5 SP1 и 4.0 Beta 1).
Смотрите этот пост для получения дополнительной информации о FK Ассоциации
В то же время ваш единственный вариант - это, вероятно, скрыть все это за процедурами DefiningQueries, CUD и т. Д.
Если ваш первичный ключ является составным ключом, все ваши отношения с внешним ключом также должны использовать весь составной ключ (все ключевые столбцы) для справки - я не вижу никакого способа обойти это, это основной принцип реляционной базы данных дизайн, правда.
Это определенно одна из основных причин, по которой я бы предпочел использовать замещающий столбец в главной таблице для первичного ключа вместо составного ключа, составленного из столбцов фактических данных.
ОБНОВЛЕНИЕ: да, основываясь на ваших комментариях, вы абсолютно правы - дизайн БД надежен. Не совсем уверен, почему EF не может справиться с этим ....
Марк