Ошибка один в один в Entity Framework 4 - PullRequest
3 голосов
/ 10 ноября 2010

Я уже прочитал Проблемы сопоставления One-to-One Entity Framework , и это не повторяется, поскольку спецификации бизнес-правил здесь иные.

Есть две таблицы: Счета-фактуры и Заказы.

Invoices
-> InvoiceID (Primary, Auto Number)
Orders
-> OrderID (Primary, Auto Number)
-> InvoiceID (FK InvoiceID of Invoices Table)

Теперь проблема в том, что EF требует отношения «один ко многим» для этой ассоциации, если имена свойств не совпадают.Если имена свойств совпадают, то это служит цели производного класса, но здесь Order не является производным классом или счетом.

InvoiceID (ы) генерируются для каждой корзины покупок, но OrderID (ы) генерируются только дляоплаченные счета, поэтому у каждого заказа есть InvoiceID, но у каждого заказа нет соответствующего счета-фактуры.

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

Однако в настоящее время, если я изменяю модель следующим образом, она работает

Invoices
-> InvoiceID (Primary, Auto Number)
Orders
-> OrderID (Auto Number)
-> InvoiceID (Primary, FK InvoiceID of Invoices Table)

Но это хорошая практика??Потому что по определению InvoiceID таблицы Orders, безусловно, будет уникальным, но мы будем ссылаться везде на OrderID для сравнения и множества других ссылок.Я знаю, что могу проиндексировать свойство, но я не чувствую, что этот дизайн идеален.

One to One Error

1 Ответ

2 голосов
/ 10 ноября 2010

То, что кажется очевидным решением здесь, это изменить связь 1: * между Счетом и порядок в EDM в 1: 1 ассоциацию. Однако, как вы поняли, отображение не будет проверьте, если у вас есть ассоциация внешнего ключа между двумя объектами, как в вашей модели.

Единственный способ сопоставить уникальную ассоциацию внешнего ключа - использовать Независимая ассоциация . Это тот же тип ассоциации, который был у нас в EF3.5, где внешние ключи не поддерживались.

Превратить ассоциацию внешнего ключа в независимую ассоциацию означало бы удаление внешнего ключа InvoiceID из объекта Order и воссоздание ассоциации посредством сопоставлений.

Чтобы внести изменения в ассоциацию, вам необходимо сделать следующее:

  1. Удалите свойство внешнего ключа InvoiceID из сущности заказа.
  2. Выберите Ассоциирование между Счетом и Заказом.
  3. В окне Свойства для ассоциации откройте Ссылочные ограничения по щелкнув по эллипсу рядом с этим свойством.
  4. Удалите ограничение, нажав кнопку Удалить.
  5. Щелкните правой кнопкой мыши ассоциацию в Designer и выберите Table Mapping из контекстного меню.
  6. В окне Сведения о сопоставлении щелкните элемент , чтобы открыть раскрывающийся список.
  7. В раскрывающемся списке выберите Порядок. Отображения должны заполняться автоматически.
  8. Вернитесь в окно свойств для ассоциации.
  9. Для свойства «Кратность 2», которое в настоящее время имеет значение * Коллекция заказов, измените это свойство на 1 (один из заказов), используя его раскрывающийся список.
  10. Подтвердите модель, щелкнув правой кнопкой мыши область проектирования и выбрав Подтвердить. Вы увидите, что сообщение об ошибке, связанное с этим отображением, исчезло.

Когда вы столкнетесь с этой проблемой в вашем приложении, вам придется решить, что является более важным для вашей модели и логики вашего приложения: скаляр внешнего ключа (например, Order.InvoiceID) или возможность определить связь 1: 1 между одним объектом (Счет-фактура) и другим (Заказ), когда они соединены через внешний ключ (InvoiceID).

Хорошая новость заключается в том, что новый EF4.0 Lazy Loading будет по-прежнему работать с независимыми ассоциациями, только внешний ключ не раскрывается. Чтобы получить это, вам нужно перейти к свойству навигации (Invoice) и прочитать его InvoiceID, как показано ниже:

Order order = context.Orders.First();
int invoiceID = order.Invoice.InvoiceID;

Или вы можете использовать приведенный ниже код, чтобы прочитать его прямо на объекте Order без необходимости использовать свойство Lazy Load или Eager Load Invoice:

int invoiceID = order.InvoiceReference.EntityKey.EntityKeyValues[0].Value;
...