Entity Framework сопоставляет два столбца таблицы с одним и тем же ключом связанной таблицы

Я нахожусь в ситуации, когда у меня есть таблица с именем Elements. Теперь я создаю таблицу с именем Divergences, в которой будут храниться пары Elements. Цель Divergence состоит в том, чтобы проверить, есть ли у двух Elements расходящиеся ответы.

Element               Divergence
---------             ----------
ElementId             ElementId1
                      ElementId2

В приведенной выше схеме таблицы ElementId1 и ElementId2 являются внешними ключами, сопоставленными с ElementId в таблице Elements, и формируют составной первичный ключ для таблицы Divergence.

Я использую подход Database First, где я создаю таблицы в SQL Server Management Studio, а затем делаю Update Model from Database... в Entity Framework Designer.

Проблема, с которой я столкнулся, заключается в том, что когда EF Designer генерирует модель, он создает 2 набора ICollection<Element> внутри класса Element, а именно Elements и Elements1.

введите здесь описание изображения

Это не дает мне Divergences DbSet.

То, что я хотел бы иметь, это класс Divergence, где я бы сделал что-то вроде этого в коде:

Divergence d = new Divergence();
d.Element1 = element1;
d.Element2 = element2;

Database.Divergences.Add(d);
Database.SaveChanges();

и позже:

Element e = Database.Elements.Single(e => e.ElementId == 7);

var divergences = e.Divergences;

Я попытался добавить новый столбец в таблицу Divergence следующим образом:

Element               Divergence
---------             ------------
ElementId             DivergenceId
                      ElementId1
                      ElementId2

Это правильно приводит к отношению 1 <-> * в Entity Framework Designer. В конце концов я получаю Divergences DbSet, но свойство DivergenceId бесполезно в коде, и я все еще получаю 2 набора в классе Element. Важно отметить, что ElementId1 и ElementId2 по-прежнему образуют составной первичный ключ.

Как вы думаете, как правильно изобразить эту конкретную ситуацию? Спасибо за отзыв.


person Leniel Maccaferri    schedule 19.07.2013    source источник


Ответы (1)


Вместо...

Divergence d = new Divergence();
d.Element1 = element1;
d.Element2 = element2;

Database.Divergences.Add(d);
Database.SaveChanges();

... вы могли бы использовать:

element1.Elements = new List<Element>();
// if that collection isn't already instantiated, for example in the constructor
element1.Elements.Add(element2);

Database.SaveChanges();

Это создаст точно такие же операторы SQL INSERT для таблицы ссылок без необходимости наличия сущности Divergence. (Отслеживание изменений распознает, что вы изменили связь, добавив элемент в коллекцию, и выведет необходимые команды SQL из этого изменения. element1 и element2 должны быть присоединены к контексту в состоянии Unchanged, но это также требуется для вашего исходного кода в для правильной работы.)

Также вместо...

Element e = Database.Elements.Single(e => e.ElementId == 7);
var divergences = e.Divergences;

... вы можете получить столбцы из таблицы Divergences следующим образом:

var divergences = Database.Elements.Where(e => e.ElementId == 7)
    .SelectMany(e1 => e1.Elements.Select(e2 => new
    {
        ElementId1 = e1.ElementId,
        ElementId2 = e2.ElementId,
    }))
    .ToList();

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

Однако вы можете удалить одну из коллекций (просто удалите ее на поверхности модели). На мой взгляд, наличие обоих немного сбивает с толку в этой модели. Или хотя бы переименовать их в SourceElements и TargetElements например :)

person Slauma    schedule 19.07.2013
comment
Шикарный Слаума! Вот и все... Я собираюсь реализовать это таким образом, поскольку, как вы сказали, нет встроенной функциональности для отображения так, как я хотел. Спасибо вам большое за ваше внимание! :) - person Leniel Maccaferri; 20.07.2013