Свободный API EF 4.1. Как сопоставить два объекта при использовании существующей таблицы соединений с тремя столбцами идентификаторов?

У меня есть три объекта (EntityA, EntityB, EntityC) в коде и их соответствующие таблицы (TableA, TableB, TableC) в базе данных. У меня также есть существующая таблица соединений с тремя столбцами идентификаторов (TableA_ID, TableB_ID, TableC_ID).

В коде сущности связаны следующим образом:

MODELS:
public class EntityA
{
   public Guid EntityA_ID { get; set }
   .....
   // Each EntityA can be associated with 0 or Many EntityB
   public virtual ICollection<EntityB> EntityBCollection { get; set; }
}

public class EntityB
{
   public Guid EntityB_ID { get; set; }
   .....
   // Each EntityB can be associated with 0 or Many EntityA
   public virtual ICollection<EntityA> EntityACollection { get; set; }

   // Each EntityB can be assocated with 0 or Many EntityC,
   // but it becomes 0 or 1 when EntityB is associated with an EntityA
   public virtual EntityC EntityC { get; set; }
}

public class EntityC
{
   public Guid EntityC_ID { get; set; }
   ......
   // Each EntityC an only be associated with a EntityB
   // an EntityC does not exist on its own
   public virtual EntityB EntityB { get; set; }
}

DATA CONTEXT:
modelBuilder.Entity<EntityB>()
                .HasOptional(entityb => entityb.EntityC)
                .WithRequired(entityc => entityc.EntityB)
                .Map(map =>
                {
                    map.ToTable("ThreeIDColumnJoinTable").MapKey(new string[]{"EntityA_ID", "EntityB_ID", "EntityC_ID"});

                });

Я продолжаю получать следующую ошибку:

Unable to determine the principal end of an association between the types 'EntityC' and 'EntityB'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations. 

Любые идеи о том, как я могу перенастроить сопоставление в КОНТЕКСТЕ ДАННЫХ, чтобы оно не приводило к ошибке, а также включало отношение EntityA, указанное в ThreeIDColumnJoinTable?


person fuzzlog    schedule 16.01.2012    source источник
comment
У вас нет сущности для записей в таблице соединений? Также я думаю, что вы неправильно используете метод Map в последней строке. Эта версия предназначена только для сопоставления имен столбцов внешнего ключа (см. описание в Intellisense).   -  person Slauma    schedule 16.01.2012
comment
Slauma не создавал объект для таблицы соединения, так как мне никогда не приходилось этого делать ранее (для прямых отношений «многие к маю» с двумя столбцами). Кроме того, код карты был моей последней попыткой использовать все различные премутации, которые я мог придумать. Я попробую создать объект таблицы соединений, чтобы посмотреть, что еще получится. Спасибо.   -  person fuzzlog    schedule 16.01.2012
comment
Да, для таблиц соединения «многие ко многим» сущность не нужна. Но эта таблица должна иметь ровно два столбца, которые образуют составной ключ и являются FK для связанных таблиц. Никакие другие типы соединяемых таблиц не допускаются.   -  person Slauma    schedule 16.01.2012
comment
Если я называю EntityD сущностью составного ключа, значит ли это, что мне также нужно добавить свойства навигации для EntityD в EntityA, EntityB и EntityC, а также добавить свойства навигации для Entiteis A, B, C в D? Извините, если это звучит невежественно, но EF не моя сильная сторона. Спасибо   -  person fuzzlog    schedule 16.01.2012
comment
Обычно для ассоциации требуется только одно свойство навигации. Второе всегда необязательно. Кстати: почему бы вам просто не сопоставить между A и B нормальным отношением «многие ко многим» и между B и C обычным отношением «один к одному»? Я не понимаю необходимости иметь третий ключевой столбец в этой таблице соединений.   -  person Slauma    schedule 17.01.2012
comment
Отсутствие опыта в этом вопросе. Я попробую маршрут AB BC, который вы упомянули. Спасибо.   -  person fuzzlog    schedule 17.01.2012
comment
Ваше сопоставление между B и C уже в порядке, если вы просто удалите .Map(...) в конце.   -  person Slauma    schedule 17.01.2012


Ответы (1)


// Каждый EntityB может быть связан с 0 или Many EntityC, но становится 0 или 1, когда EntityB связан с EntityA

В таком случае ваш EntityB имеет неправильное свойство навигации. Так должно быть:

public class EntityB
{
   public Guid EntityB_ID { get; set; }
   .....
   // Each EntityB can be associated with 0 or Many EntityA
   public virtual ICollection<EntityA> EntityACollection { get; set; }

   public virtual ICollection<EntityC> EntityCCollection { get; set; }
}

Вам нужна коллекция EntityC для поддержки части «Многие». Вторая часть правила не может быть применена базой данных/моделью. Это должно обеспечиваться логикой вашего приложения.

Остальную часть вашей модели можно использовать как есть. Удалите это плавное отображение, и вы должны получить отношение «многие ко многим» между A и B и отношение «один ко многим» между B и C. Это именно то, что утверждают ваши правила.

Нет ничего лучше автоматического много-ко-многим для трех столов. Если вам это нужно (не ваш текущий случай), вы должны сопоставить соединительную таблицу как четвертый объект и указать свойства навигации из трех других объектов в этот новый объект, обеспечивающий реляционный мост.

person Ladislav Mrnka    schedule 17.01.2012
comment
Итак, основываясь на информации, которую вы и Слаума предоставили до сих пор, кажется, что если я создам модель для своих таблиц (включая таблицы соединений/соединений), а затем добавлю запись DbSet для каждой из этих таблиц в моем классе контекста и затем я добавляю соответствующие навигационные свойства к соответствующим моделям, тогда мне вообще не придется использовать свободный метод API .Map(...) ModelBuilder.Entity‹T›()? Это верное утверждение? - person fuzzlog; 18.01.2012
comment
Я считаю, что вам не понадобится объект для соединительной таблицы, а только для A, B и C. В противном случае ваше понимание правильное. - person Ladislav Mrnka; 18.01.2012
comment
Спасибо обоим за расширение моего понимания. Я был настроен использовать .Map(...) так как это то, что я видел в большинстве примеров. Создание моделей для таблиц соединений и добавление правильных свойств навигации в другие модели решили мою проблему. - person fuzzlog; 18.01.2012