Разделение объекта, когда ключевой столбец имеет разные имена?
-
28-10-2019 - |
Вопрос
Я использую Entity Framework 4.3.1 Code-First, и мне нужно разделить объект между двумя таблицами. Таблицы имеют общий первичный ключ, равный 1: 1, но столбцы имеют разные имена в каждой таблице.
Я не контролирую структуру данных и не могу запрашивать какие-либо изменения.
Так, например, таблицы SQL могут быть
И это будет моя сущность ...
родовое словоА вот карта, которая у меня есть.
родовое словоПоскольку общий для них ключ имеет другое имя столбца, я не знаю, как его сопоставить. Это сопоставление будет компилироваться, но не удастся во время выполнения, потому что EF выдает SQL в поисках столбца «ThePrimaryKeyId» в таблице «ExtendedTable», которой не существует.
ИЗМЕНИТЬ Чтобы прояснить, то, что я определил выше, может (и работает) работать, если ПК в «ExtendedTable» следует соглашениям об именах. Но это не так, и я не могу изменить схему.
По сути, то, что мне нужно, чтобы испускать EF, - это оператор SQL, например
родовое словоНо единственное, что он, кажется, хочет испустить, это
родовое словоИзменить Я снова попробовал подход 1 к 1 по предложению NSGaga. Не получилось, но вот результаты. Сущности
родовое словоВот классы сопоставления
родовое словоЭта настройка получает сообщение
родовое словоИзменение последней линии карты на
родовое словоВозвращает это сообщение
родовое слово Изменение сопоставленного ключа для использования столбца из родительской таблицы, MapKey("ThePrimaryKeyId")
. возвращает это сообщение
Удаление свойства Id
из класса ExtEntity
вызывает ошибку, поскольку в этом случае объект не имеет определенного ключа.
Решение
Я не могу найти ничего, что конкретно указывало бы на то, что имя столбца должно быть одинаковым в обеих таблицах;но я также не могу найти ничего, что говорило бы, что это не так, или объясняло бы, как вы бы сопоставили этот сценарий.Каждый пример, который я могу найти, имеет ключ с тем же именем в обеих таблицах.Мне кажется, это дыра в дизайне DbContext.
Другие советы
Я работал над этой проблемой в течение нескольких дней, и в итоге я установил имя столбца для поля Id в контексте фрагмента сопоставления.Таким образом, вы можете присвоить идентификатору (или внешнему ключу, зависящему от идентификатора) имя, отличное от идентификатора основной таблицы.
родовое словоЕсли вы запустите и отладите это, вы обнаружите, что это даст вам что-то вроде того, что вы хотите:
родовое словоПереместите HasColumnName в сопоставление:
родовое словоЗдесь нет Visual Studio, но попробуйте это с подходом "один к одному":
this.HasRequired (e=> e.ExtendedProperties) .HasConstraint ((e, m)=> e.Id== m.Id);
Обновление:
Вот несколько ссылок, которые могут помочь (не удалось найти настоящую ссылку)
Какдля объявления взаимно однозначной связи с помощью Entity Framework 4 Code First (POCO)
Entity Framework 4 CTP4 Code First: как работать с нестандартными именами первичных и внешних ключей
И просто чтобы предоставить (как я и обещал) сопоставление 1 к 1 (две сущности, две таблицы), чего это стоит.
Вот что работает для меня и должно в вашем случае ...
... и тестовый код вроде ...
родовое словоЭто создает следующий сценарий SQL, таблицы ...
родовое слово И примечание из нашего обсуждения выше ...
Это не «расщепление», а
(a) сначала код IMO не допускает ничего подобного (я сначала попробовал это, а также изменил миграции вручную, но это «внутренне», все основано на том, что ожидаемые имена столбцов совпадают, и, похоже, нет никакого способа обойти это, поскольку не меньше этой версии EF.
(b) разумная структура таблицы - таблицы могут быть сделаны так, чтобы они выглядели именно так, как вам нужно (как я сказал ранее, я использовал его, чтобы связать существующие таблицы членства aspnet (которые я не мог изменить) в мою таблицу пользователей, у которой есть собственный пользователь -id указывает на внешнюю / aspnet таблицу и идентификатор.
Верно, вы не можете сделать это, используя один класс модели C #, но сторона C # намного более гибкая, и если вы можете контролировать C #, который должен давать тот же эффект, по крайней мере, на мой взгляд (как в тесте, вы всегда можете получить к нему доступ через расширенную сущность, как расширенные, так и основные столбцы, и они всегда сопоставляются 1 к 1 и остаются «синхронизированными».
Надеюсь, это поможет некоторым
ПРИМЕЧАНИЕ: вам не нужно беспокоиться об идентификаторе fk и т. Д. - просто всегда открывайте и добавляйте запись Main через MainEntry, и id-s будет в порядке.
ИЗМЕНИТЬ:
Вы также можете сделать следующее, чтобы создать видимость того, что вам нужно иметь дело только с одним классом (т. Е. Своего рода разделение)
... и используйте его вот так ...
родовое слово ... также вы можете изменить направление fk, выполнив код WithRequiredPrincipal
вместо зависимого.
(также все ссылки должны быть без «виртуальных», если вам требуется индивидуальный подход)
(и MainTable можно сделать «внутренним», так как он здесь, поэтому он не виден снаружи - он не может быть вложенным, поскольку EF не позволяет - обрабатывается как NotMapped)
... ну, это лучшее, что я мог сделать :)
Похоже, это было исправлено в Entity Framework 6. См. эту проблему http://entityframework.codeplex.com/ workitem / 388
Я хотел бы предложить использовать некоторые аннотации данных, например:
родовое слово Я столкнулся с этой проблемой и решил ее, добавив атрибут Column, чтобы он соответствовал именам обоих столбцов.
[Key]
[Column("Id")]
public int GroupId { get; set; }