Инициализация новых объектов вызывает исключение FKC#

Место общения программистов C#
Ответить
Гость
 Инициализация новых объектов вызывает исключение FK

Сообщение Гость »


У меня есть интеграционный тест, демонстрирующий странное поведение, и я думаю, это потому, что я что-то не понимаю в EF Core.

Приведенный ниже код — это всего лишь часть теста «Упорядочить», но он вызывает у меня проблемы. Он должен сделать следующее:
[*]Настройте Contact «Оператора», который содержит ссылку на существующую запись ContactType в базе данных (по сути, Enum). [*]Настройте Contact «Венора», который содержит ссылку на существующий ContactType в базе данных (по сути, Enum).3. Сохраните изменения, чтобы сохранить их. Неработающий пример
[Факт] общественная пустота StackOverflow_BrokenExample() { // Договариваться var CarrierContactType = Context.ContactTypes.FirstOrDefault(ct => ct.Id == ContactTypeEnum.Carrier); var CarrierContact = новый контакт { Имя = «Контакт оператора связи», Адрес1 = "456 Какая-то улица", Актив = правда, ContactTypes = новый список() { операторContactType, }, }; Context.Contacts.Add(перевозчикContact); varvendorContactType = Context.ContactTypes.FirstOrDefault(ct => ct.Id == ContactTypeEnum.Vendor); варvendorContact = новый контакт() { Имя = «Контактное лицо поставщика тестов», Адрес1 = "Другая улица, 123", Актив = правда, ContactTypes = новый список() { вендорКонтактТип, }, }; Context.Contacts.Add(vendorContact); Контекст.СохранитьИзменения(); } Инструкция MERGE конфликтовала с ограничением FOREIGN KEY «FK_ContactTypeXrefs_Contacts_ContactId». Конфликт произошел в базе данных «VF_BillOfLading», таблица «dbo.Contacts», столбец «Id».

Сгенерированный SQL включает в себя следующее:

dbug: 20.09.2023 12:15:31.172 CoreEventId.ForeignKeyChangeDetected[10803] (Microsoft.EntityFrameworkCore.ChangeTracking) Свойство внешнего ключа «Contact.Id» было обнаружено как измененное с «-2147482647» на «1» для объекта с ключом «{Id: 1}». dbug: 20.09.2023 12:15:31.179 CoreEventId.ForeignKeyChangeDetected[10803] (Microsoft.EntityFrameworkCore.ChangeTracking) Свойство внешнего ключа «Contact.Id» было обнаружено как измененное с «-2147482646» на «2» для объекта с ключом «{Id: 2}». информация: 20.09.2023 12:15:31.227 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command) Выполнено DbCommand (44 мс) [Parameters=[@p38='-2147482647', @p39='2', @p40='-2147482646', @p41='3'], CommandType='Text', CommandTimeout='30 '] ВЫКЛЮЧИТЬ IMPLICIT_TRANSACTIONS; УСТАНОВИТЬ NOCOUNT ON; ОБЪЕДИНИТЬ [ContactTypeXrefs] ИСПОЛЬЗОВАНИЕ ( ЗНАЧЕНИЯ (@p38, @p39, 0), (@p40, @p41, 1)) AS i ([ContactId], [ContactTypeId], _Position) ВКЛ 1=0 КОГДА НЕ СОВПАДАЕТСЯ, ТОГДА ВСТАВИТЬ ([ContactId], [ContactTypeId]) ЗНАЧЕНИЯ (i.[ContactId], i.[ContactTypeId]) ВЫХОД INSERTED.[Id], INSERTED.[Создан], i._Position; Рабочий пример [Факт] общественная пустота StackOverflow_WorkingExample() { // Договариваться var CarrierContact = новый контакт { Имя = «Контакт оператора связи», Адрес1 = "456 Какая-то улица", Актив = правда, }; Context.Contacts.Add(перевозчикContact); var CarrierContactType = Context.ContactTypes.FirstOrDefault(ct => ct.Id == ContactTypeEnum.Carrier); CarrierContact.ContactTypes.Add(carrierContactType); варvendorContact = новый контакт() { Имя = «Контактное лицо поставщика тестов», Адрес1 = "Другая улица, 123", Актив = правда, }; Context.Contacts.Add(vendorContact); varvendorContactType = Context.ContactTypes.FirstOrDefault(ct => ct.Id == ContactTypeEnum.Vendor); vendorContact.ContactTypes.Add(vendorContactType); Контекст.СохранитьИзменения(); } Мысли и устранение неполадок [*]Похоже, что EF не может соединить записи ContactType и Contact при инициализации в одном и том же объекте. SQL предполагает, что он пытается вставить запись ContactTypeXref с -21474822647 и -21474822646 в качестве поля Contact.Id (значения по умолчанию), хотя в журнале указано, что идентификаторы были просто установлено значение 1 и 2 соответственно.
[*]
Когда объекты Contact инициализируются с пустыми свойствами ContactType, а затем изменяются позже, я подозреваю, что трекер EF может отслеживать, а затем вставлять внешнюю ссылку записывает соответственно.
[*]
Ниже приведен класс ContactTypeConfiguration. Возможно, здесь отсутствует поле, специально обозначенное как ключ?

// ContactType EntityTypeConfiguration public void Configure (строитель EntityTypeBuilder) { builder.ToTable( Имя Таблицы, x => x.HasComment( «Табличное представление ContactTypeEnum для ссылочной целостности. Не редактируйте без соответствующего изменения Enum в коде.»)); builder.Property(x => x.Id) .ValueGeneratedNever(); строитель.HasData( новый список { new() { Id = ContactTypeEnum.Carrier, Name = "Carrier" }, new() { Id = ContactTypeEnum.Customer, Name = "Клиент" }, new() { Id = ContactTypeEnum.Shipper, Name = "Отправитель" }, new() { Id = ContactTypeEnum.Vendor, Name = "Поставщик" } , }); } // Контактная конфигурация типа сущности public void Configure (построитель EntityTypeBuilder) { // Основной ключ builder.HasKey(x => x.Id); builder.Property(x => x.Id) .HasColumnOrder(0); // Инцесы builder.HasIndex(x => x.Name); builder.HasIndex(x => x.Address1); builder.HasIndex(x => x.Address2); builder.HasIndex(x => x.Address3); builder.HasIndex(x => x.City); builder.HasIndex(x => x.State); builder.HasIndex(x => x.PostalCode); // Аудит builder.Property(x => x.Created) .HasColumnOrder(1); builder.Property(x => x.Modified) .HasColumnOrder(2); builder.Property(x => x.CreatedBy) .HasColumnOrder(3); builder.Property(x => x.ModifiedBy) .HasColumnOrder(4); // Управление версиями builder.Property(x => x.Version) .IsRowVersion() .HasColumnOrder(5); // Мягкое удаление builder.Property(x => x.IsDeleted) .HasColumnOrder(6); // Настройки свойств builder.Property(x => x.IsActive) .HasColumnOrder(7); // Отрезаем... сопоставления свойств // Связь «многие ко многим» между контактами и типами контактов builder.HasMany(x => x.ContactTypes) .Со многими() .UsingEntity( ContactTypeXrefTableName, l => l.HasOne().WithMany().HasForeignKey(e => e.ContactTypeId), r => r.HasOne().WithMany().HasForeignKey(e => e.ContactId), г => { // Настройка свойства полезной нагрузки z.Property(e => e.Created).HasDefaultValueSql(SqlServerSysDatetimeOffset); }); } [*]Это таблица внешних ссылок, разработанная EF: migrationBuilder.CreateTable( имя: "ContactTypeXrefs", столбцы: таблица => новый { Id = table.Column(тип: «int», значение null: false) .Annotation("SqlServer:Identity", "1, 1"), ContactId = table.Column(тип: «int», значение null: false), ContactTypeId = table.Column(тип: «int», значение null: false), Created = table.Column(type: «datetimeoffset», значение null: false, defaultValueSql: «SYSDATETIMEOFFSET()»), }, ограничения: таблица => { table.PrimaryKey("PK_ContactTypeXrefs", x => x.Id); таблица.ForeignKey( имя: "FK_ContactTypeXrefs_ContactTypes_ContactTypeId", столбец: x => x.ContactTypeId, PrincipalTable: "Типы контактов", PrincipalColumn: «Идентификатор», onDelete: ReferentialAction.Cascade); таблица.ForeignKey( имя: "FK_ContactTypeXrefs_Contacts_ContactId", столбец: x => x.ContactId, PrincipalТаблица: «Контакты», PrincipalColumn: «Идентификатор», onDelete: ReferentialAction.Cascade); }); Я что-то упустил или нет способа сразу инициализировать полностью гидратированный объект в EF?
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»