Определение структуры Entity Framework 1: 1 - PullRequest
12 голосов
/ 24 января 2009

Я пытаюсь определить связь 1: 1 между двумя сущностями (одна сопоставляется с таблицей, а другая с представлением - используя DefinedQuery) в модели Entity Framework. При попытке определить сопоставление для этого в конструкторе, я выбираю таблицу (1) или представление для сопоставления ассоциации. Что я должен выбрать? Я могу выбрать любую из двух таблиц, но затем я вынужден выбрать столбец из этой таблицы (или представления) для каждого конца отношения. Я ожидал, что смогу выбрать столбец из одной таблицы для одного конца ассоциации и столбец из другой таблицы для другого конца ассоциации, но сделать это невозможно.

Здесь я выбрал отображение в представление "DW_ WF_ClaimInfo", и оно заставляет меня выбрать два столбца из этого представления - по одному для каждого конца отношения.

Я также попытался определить отображение вручную в XML следующим образом:

<AssociationSetMapping Name="Entity1Entity2" TypeName="ClaimsModel.Entity1Entity2"
     StoreEntitySet="Entity1">
  <EndProperty Name="Entity2">
    <ScalarProperty Name="DOCUMENT" ColumnName="DOCUMENT" />
  </EndProperty>
  <EndProperty Name="Entity1">
    <ScalarProperty Name="PK_DocumentId" ColumnName="PK_DocumentId" />
  </EndProperty>
</AssociationSetMapping>

Но это дает: Ошибка 2010: Столбец DOCUMENT, указанный как часть этого MSL, не существует в MetadataWorkspace. Похоже, он по-прежнему ожидает, что оба столбца будут взяты из одной таблицы, что для меня не имеет смысла.

Кроме того, если я выберу одну и ту же клавишу для каждого конца, например ::

<AssociationSetMapping Name="Entity1Entity2" TypeName="ClaimsModel.Entity1Entity2"
     StoreEntitySet="Entity1">
  <EndProperty Name="Entity2">
    <ScalarProperty Name="DOCUMENT" ColumnName="PK_DocumentId" />
  </EndProperty>
  <EndProperty Name="Entity1">
    <ScalarProperty Name="PK_DocumentId" ColumnName="PK_DocumentId" />
  </EndProperty>
</AssociationSetMapping>

Я тогда получаю:

Error 3021: Problem in Mapping Fragment starting at line 675: Each of the following
columns in table AssignedClaims is mapped to multiple conceptual side properties:
  AssignedClaims.PK_DocumentId is mapped to
    <AssignedClaimDW_WF_ClaimInfo.DW_WF_ClaimInfo.DOCUMENT,
    AssignedClaimDW_WF_ClaimInfo.AssignedClaim.PK_DocumentId>

Что я не получаю?

Ответы [ 9 ]

6 голосов
/ 24 января 2009

Вы должны выбрать таблицу, которая содержит внешний ключ. Следующим шагом является удаление этого внешнего ключа из сущности, поскольку он уже выражен с использованием только что созданного отношения.

Пример:

table A
-------
A_ID int
B_ID int


table B
-------
B_ID int

В этом случае вы бы выбрали таблицу A в конструкторе, так как она содержит внешний ключ. Также вам нужно будет удалить B_ID из объекта A впоследствии.

0 голосов
/ 04 июля 2012

После почти целого дня работы над этим я понял это! На самом деле, я нашел 2 разных способа решения этой проблемы, предполагая, что у меня та же проблема, что и у Крейга.

Во-первых, ответ driAn на самом деле не помогает (еще раз, если у Крэйга та же проблема, что и у меня), поскольку проблема в том, что в таблице А. нет отдельного внешнего ключа. Первичный ключ таблицы А точно такой же первичный ключ для таблицы B! В частности, в моем случае я использую представление и таблицу, а не две таблицы:

table A
-------
A_ID int
col1 int
col2 int

view A_extra
-------
A_ID int
col3 int

Итак, вот решения, которые я нашел:

1. Сопоставьте две разные сущности, но используйте взлом. Таким образом, вся проблема с ответом driAn заключается в том, что у нас нет отдельного столбца внешнего ключа для сопоставления, который мы затем можем удалить из свойств (мы не можем удалите его из свойств, потому что это первичный ключ представления A_extra!). Так что взломать безумно просто, как только вы это поймете: отредактируйте A_extra и просто создайте копию A_ID и сделайте его внешним ключом замены:

table A
-------
A_ID int
col1 int
col2 int

view A_extra
-------
A_ID int
A_FK_ID int        
col3 int

A_FK_ID просто определяется как 'A_ID as A_FK_ID' в SQL представления, и он всегда будет иметь точно такое же значение, как A_ID.

Теперь, для структуры сущностей, это очень знакомый сценарий. Просто создайте связь 1-к-1, сопоставьте ассоциацию с A_extra и сопоставьте свойство A_ID в таблице A с A_FK_ID и свойство A_ID в A_extra с A_ID. Теперь вы больше не заставляете одну и ту же колонку выполнять двойную функцию согласно EF! Однако забавно то, что A_FK_ID всегда будет идентичен A_ID в A_extra.

Теперь у вас есть свойство навигации к A_extra, и col3 доступен, как вы и ожидали. Более того, вы по-прежнему можете изначально изменять table_A, так как EF видит, что это таблица (если вы сделали одно представление из этой комбинации и импортировали его в EF, вы не можете обновить его изначально).

2. Сопоставьте таблицу и представление с одной сущностью. Для этого решения вам не нужен хак, и это предпочтительно, потому что вам не нужно переходить через свойство навигации, чтобы перейти к col3.

Чтобы получить эту конфигурацию, добавьте A и A_extra в EF. Скопируйте и вставьте col3 из A_extra в A, так что теперь у вас есть несопоставленное свойство "col3", расположенное в A, и ничего в A_extra. Теперь перейдите к отображению для A и добавьте A_extra как представление для отображения (так, чтобы сущность «A» теперь отображалась как в таблицу «A», так и в представление «A_extra»). Сопоставьте свойство col3 (в объекте A) со столбцом col3 (в представлении A_extra). Теперь вот как вы показываете EF, как объединить эти два элемента для создания единого объекта: сопоставить столбец A_ID в A_extra с идентификатором свойства в объекте A. Если вы заметили, у вас теперь есть два столбца, сопоставленных с одним имущество. Это нормально, поскольку они представляют одно и то же, и именно так EF знает, как присоединиться к этому столбцу.

Теперь, чтобы закончить очистку, вам нужно удалить плавающую сущность "A_extra" в конструкторе. (Возможно, вы захотите убедиться, что он больше не отображается для просмотра A_extra, просто чтобы быть уверенным, что он также не убирает отображение магазина для A_extra - я надеюсь, что этого не произойдет, поскольку объект A теперь сопоставлен с ним). Теперь вы сможете создавать и получать доступ к col1, col2 и col3 из сущности A!

Круто то, что вы можете корректно обновить данные до col1 и col2, так как они сопоставлены с таблицей (A), но EF помешает вам, как следует, обновить col3, поскольку они сопоставлены с представлением (A_extra) , Это удобнее, чем сделать A комбинированным представлением в БД и импортировать его, потому что EF помешает вам обновить любых столбцов, поскольку они все из представления, насколько это касается.

Уфф, я так рад, что наконец-то это сработало. Надеюсь, мои решения помогли вам, ребята!

-Роберт

0 голосов
/ 06 июля 2011

Проще говоря, я сделал следующее:

  1. Создать таблицу с первичным ключом (PK) для столбца.
  2. Создание представления с внешним ключом (FK) для столбца. или наоборот.
  3. В редакторе диаграмм edmx создал Ассоциацию.
  4. Скомпилируйте код.

В коде метаданных XAML Родительский объект, имеющий PK, покажет дочерний объект Entity, который может быть связан для связывания элементов.

0 голосов
/ 09 декабря 2010

Я получил ту же ошибку, когда попытался сделать один-к-одному между двумя таблицами, соединенными по их первичным ключам. (Нет, я не проектировал БД). Таким образом, решение по удалению FK не работает - FK - это также PK, поэтому вы не собираетесь его удалять. В качестве эксперимента я изменил одну сторону ассоциации на 0..1, и вот, модель скомпилирована без ошибок. Я использовал EF3.5

0 голосов
/ 05 мая 2010

В Entity Framework, в концептуальном проекте не должно быть внешних ключей. Я считаю, что это теперь разрешено в EF4 (с некоторыми изменениями), но в EF3.5 это невозможно .

Чтобы исправить это, просто удалите все свойства, которые представляют внешние ключи в EF-конструкторе. Не удаляйте первичные ключи!

Если затем вы получите «Конец ассоциации не сопоставлен ..» ошибка, см. (Мой ответ) этот пост .

0 голосов
/ 29 апреля 2010

Сначала создайте внешний ключ в базе данных, а затем создайте связь или обновите модель из базы данных.

0 голосов
/ 08 декабря 2009

Я согласен, что способ настройки выглядит нелогичным. Для тех, кто слишком медлителен (как я), чтобы получить ответ от driAn: В сообщении на форуме ниже я вспомнил, что мы имеем дело с сущностью, а не с таблицей напрямую. Ассоциация связана с сущностью (которая может моделировать таблицу, но не обязана).

http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/2823634f-9dd1-4547-93b5-17bb8a882ac2/

Структура сущности связывает СВОЙСТВА с СТОЛОВЫЕ КОЛОННЫ . Вот почему мы должны удалить «внешний ключ» PROPERTY для ENTITY (примечание: мы не удаляем столбец таблицы). Чтобы сослаться на столбец в коде, (используя ENTITY моделирование данный пример TABLE A и TABLE B) вы должны написать что-то вроде этого:

variable_A = tableAs.A_ID
variable_B = tableAs.tableBs.B_ID

Второе назначение использует ассоциацию, определенную в объекте, для получения данных. В таблице A. PROPERTY с именем "B_ID" нет.

Это все, если я правильно понимаю :). По крайней мере, теперь для меня это правильно.

: - Dan

0 голосов
/ 16 сентября 2009

Я имел дело с унаследованным приложением, поэтому добавление дополнительного первичного ключа для меня было невозможным. Я должен был отобразить его как 1: (0 или 1), а не 1: 1, чтобы заставить его работать. Например, если у меня было две таблицы, скажем, Customer и CustomerDetails, у обеих из которых был первичный ключ с именем CustomerID. Чтобы создать ассоциацию, я должен был установить ее как 1 Клиент может относиться к (0 или 1) записям CustomerDetails. Каждый раз, когда вы вставляете клиента, не забудьте также вставить CustomerDetails, чтобы вы могли поддерживать 1: 1.

0 голосов
/ 26 марта 2009

Не обязательно получить ответ, но с Entity Framework я всегда создаю первичный ключ в каждой таблице (даже если он мне не нужен). Пример:

  • Таблица Customer имеет CustumerID в качестве первичного ключа
  • Таблица Product имеет ProductID в качестве первичного ключа
  • Таблица заказа, конечно, используйте CustomerID + ProductID в качестве первичного ключа. Ну, я также создаю один локальный первичный ключ: OrderID.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...