Моя модель данных содержит две таблицы с составными первичными ключами и ассоциативную таблицу. Часть составного первичного ключа является общей для таблиц.

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. Убедитесь, что все ключевые свойства указаны в основной роли.

Как правильно смоделировать эти отношения?

4
Michael L Perry 18 Июн 2009 в 00:09

2 ответа

Лучший ответ

Подобные перекрывающиеся FK не поддерживаются в 3.5 SP1.

Т.е.

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

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

FK1 перекрывается с FK2. Это будет поддерживаться в Beta2 EF 4. Это связано с тем, что ассоциации FK (которые доступны в Beta2) намного более гибкие, чем независимые ассоциации (которые есть в 3.5 SP1 и 4.0 Beta 1).

См. Этот пост для получения дополнительной информации о Ассоциации FK

А пока ваш единственный вариант - спрятать все это за DefiningQueries, процедурами CUD и т. Д.

  • Alex
4
Alex James 18 Июн 2009 в 02:45

Если ваш первичный ключ является составным ключом, все ваши отношения внешнего ключа также должны использовать весь составной ключ (все ключевые столбцы) для справки - я не вижу никакого способа обойти это, это основной принцип реляционной базы данных дизайн, правда.

Это определенно одна из основных причин, по которой я, вероятно, предпочел бы использовать замещающий столбец в основной таблице для первичного ключа вместо составного ключа, составленного из фактических столбцов данных.

ОБНОВЛЕНИЕ: да, судя по вашему комментарию, вы абсолютно правы - дизайн БД прочный. Не совсем понимаю, почему EF не может с этим справиться ....

Марк

1
marc_s 18 Июн 2009 в 09:28
Во внешних ключах используется весь составной ключ. UserSitePrivilege имеет два составных внешних ключа: (UserId, SiteId) и (SiteId, PrivilegeId). Но поскольку это ассоциативная таблица, она не представлена ​​как объект. Суррогатный первичный ключ в любой таблице решит проблему, но я надеюсь, что мне не придется просить администратора базы данных изменить дизайн БД только для того, чтобы удовлетворить EF. Его дизайн действителен.
 – 
Michael L Perry
18 Июн 2009 в 02:30