Entity Framework STE и ассоциации «многие ко многим» - PullRequest
0 голосов
/ 26 октября 2011

Я довольно плохо знаком с EF и STE, но недавно наткнулся на болезненный момент, и мне интересно, как другие справляются с этим ...

Например, предположим, у меня естьдва STE: сотрудник и проект.Это отношения многие ко многим.Каждый объект имеет свойство навигации для другого (т. Е. Employee.Projects и Project.Employees).

В моем пользовательском интерфейсе пользователь может создавать / редактировать Employee и связывать его с несколькими проектами.Когда пользователь готов к принятию, список сотрудников передается на сервер для сохранения.Однако, если Employee не добавлен в «список сохранения» (т. Е. Он был удален), но была установлена ​​связь с одним или несколькими проектами, метод расширения ApplyChanges может «воскресить» объект Employee, поскольку он был «подключен».«к графу объектов через ассоциацию с проектом.

Мой код« сохранения »выглядит примерно так:

 public void UpdateEmployees(IEnumerable<Entities.Employee> employees)
 {
     using (var context = new EmployeeModelContainer(_connectionString))
     {
        foreach (var employee in employees)
        {
           context.Employees.ApplyChanges(employee);
        }

        context.SaveChanges();
     }
 }

Мне удалось избежать этой проблемы до сих пор на другихГрафы объектов с использованием FK для манипулирования ассоциациями, как описано здесь: http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx

Как справиться с этим, когда задействованы свойства связи со многими из многих и навигационные свойства?

Спасибо.

1 Ответ

3 голосов
/ 13 октября 2012

Хотя этот ответ опоздал на год, возможно, он будет вам полезен (или, по крайней мере, кому-то еще)

Простой ответ таков: не позволяйте Entity Framework выводить отношения m: m. К сожалению, я не знаю, как предотвратить это , только как справиться с этим после факта.

По умолчанию, если у меня есть такая схема:

Employee        EmployeeProject    Project
-----------     ---------------    ----------
EmployeeId ---> EmployeeId    |--> ProjectId
Name            ProjectId -----    Name
...                                ...

Entity Framework увидит, что моя таблица EmployeeProject - это простая таблица ассоциаций без дополнительной информации (например, я мог бы добавить поле Date, чтобы указать, когда они присоединились к проекту). В таких случаях он отображает взаимосвязь через ассоциацию , а не сущность . Это делает код красивым, поскольку помогает уменьшить часто встречающееся несоответствие между СУБД и объектно-ориентированной разработкой. В конце концов, если бы я просто моделировал их как объекты, я бы написал так же, верно?

Однако, как вы видели, это может вызвать проблемы (даже без использования STE, которые вызывают еще БОЛЬШЕ проблем с отношениями m: m). Так что же делать разработчику?

(следующее предполагает использование базы данных ПЕРВЫЙ. Что-нибудь еще, и вы сами)

У вас есть два варианта:

  • Добавьте еще один столбец в таблицу сопоставлений, чтобы EF посчитал, что он имеет большее значение, и не может сопоставить его с сопоставлением. Это, конечно, плохой дизайн , поскольку вам, вероятно, не нужен этот столбец (в противном случае он у вас уже есть), и вы добавляете его только из-за особых особенностей ORM, который вы ' мы выбрали. Так что не надо.

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

    1. Выберите ассоциацию в конструкторе и удалите ее. Дизайнер сообщит вам, что соответствующая таблица больше не отображается, и спросит, хотите ли вы удалить ее из модели. Ответ НЕТ
    2. Создайте новый объект (не используйте его для создания ключевого свойства) и сопоставьте его с таблицей ассоциации в окне Сведения о сопоставлении
    3. Щелкните правой кнопкой мыши по вашей новой сущности и добавьте ассоциацию
    4. Исправьте значения сущности и кратности (слева должна быть ваша ассоциативная сущность с кратностью *, справа должна быть другая сущность с кратностью 1)
    5. Установите флажок «Добавить свойства внешнего ключа в сущность»
    6. Повторите для другого субъекта в ассоциации
    7. Исправьте имена свойств в объекте ассоциации (при желании ... не обязательно, но они почти наверняка ошибочны) и сопоставьте их с соответствующими столбцами в окне Сведения о сопоставлении
    8. Выберите все скалярные свойства в вашей сущности ассоциации и установите их как EntityKey = True в окне свойств

Готово!

...