Несколько добавленных объектов могут иметь один и тот же первичный ключ в базе данных

предполагая, что у меня есть следующие структуры модели для приложения asp.net mvc 5, использующего сущность framework 6

class Athlete {
 int AthleteID {get; set;}
 List<YearsAsAthlete> YearsAsAthlete {get;set;}
}

class YearsAsAthlete {
 int YearsAsAthleteID {get;set;}
 int AthleteID {get;set;}
 [ForeignKey("AthleteID")]
 Athlete Athlete {get;set;}
 List<ContractRevenue> ContractRevenue {get;set;}
 List<AdvertisementRevenue> AdvertisementRevenue {get;set;}
}

class ContractRevenue {
 int ContractRevenueID {get;set;}
 int YearsAsAthleteID {get;set;}
 [ForeignKey("YearsAsAthleteID")]
 YearsAsAthlete YearsAsAthlete {get;set;}

 List<RevenueAmounts> RevenueAmounts {get;set;}
}

class AdvertisementRevenue {get;set;}
 int AdvertisementRevenueID {get;set;}
 int YearsAsAthleteID {get;set;}
 [ForeignKey("YearsAsAthleteID")]
 YearsAsAthlete YearsAsAthlete {get;set;}

 List<RevenueAmounts> RevenueAmounts {get;set;}
}

class RevenueAmounts {
 int RevenueAmountsID {get;set;}
 int AmountPaid {get;set;}
 date DateOfPayment {get;set;}
}

Эти модели отлично работают, когда у меня их есть, у них есть отношения, и все вкусно, как горячие модные сундуки. Когда я запускаю это, база данных создает эти таблицы, а таблица RevenueAmounts получает 2 автогенерированных столбца внешнего ключа для ContracRevenue и AdvertisingRevenue.

Однако я не хочу их, поскольку они названы странно (ContractRevenue_ContractRevenueID), и мне нужен какой-то способ доступа к свойству foreginkey id в моем методе постконтроллера для добавления новых значений, которые коррелируют с правильным типом дохода.

Когда я изменю модель RevenueAmounts следующим образом:

class RevenueAmounts {
 int RevenueAmountsID {get;set;}
 int AmountPaid {get;set;}
 date DateOfPayment {get;set;}

 // ***NOTE adding foreign keys here

 int ContractRevenueID {get;set;}
 [ForeginKey("ContractRevenueID")]
 ContractRevenue ContractRevenue {get;set;}

 int AdvertisementRevenueID {get;set;}
 [ForeignKey("AdvertisementRevenueID")]
 AdvertisementRevenue AdvertisementRevenue {get;set;}
}

Я начинаю получать исключение:

[SqlException (0x80131904): введение ограничения FOREIGN KEY "FK_dbo.AdvertisementRevenue_dbo.YearsAsAthlete_YearsAsAthleteID" в таблице "AdvertisementRevenue" может вызывать циклы или несколько каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.

** EDIT **

Я отключил функцию каскадного удаления с использованием свободного API, но теперь у меня возникает другое исключение:

Невозможно определить основной конец отношения "GIP.DAL.ContractRevenue_RevenueAmounts". Несколько добавленных объектов могут иметь один и тот же первичный ключ.

Кстати, исключение возникает, когда я пытаюсь засеять кучу информации в базу данных, а затем делать context.SaveChanges() внизу (делаю это только один раз в конце)

Ответ 1

В вашем редактировании вы указываете, что "Несколько добавленных объектов могут иметь один и тот же первичный ключ". ошибка. Не зная всех подробностей о том, что вы здесь делаете, похоже, что вы создаете отношения с сущностью, из которых в контексте с одним ID есть два. Это, вероятно, новые объекты, которые еще не были сохранены, где они получают автоматически сгенерированный идентификатор из базы данных. Если отношение основано на идентификаторе, то существует некоторая двусмысленность, потому что Entity Framework не может определить, какие из новых сущностей, на которые фактически указывает связь, - оба они имеют идентификатор, на который указывает связь.

Существует два возможных исправления.

  • Создайте временный уникальный идентификатор для объектов, созданных в контексте. Entity Framework откажется от этого, поскольку объект сохраняется, но до этой точки он может использовать его, чтобы передать один новый объект отдельно от другого. Я использовал отрицательные целые числа для этой цели в прошлом.

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

Ответ 2

Это происходит потому, что Entity Framework не может определить, какой объект в рамках отношения является родительским, когда включено Cascade delete.

Вы используете Code First? Когда Migration будет сгенерирован, вы увидите вариант для каскадного удаления в объявлении таблицы. Это должно быть разрешено, если вы установите значение false.

Однако большая проблема заключается в том, что вы создаете отношения объектов, которые не реализуют Aggregate Root, которые чаще всего избегают этой проблемы.