EF6.0 "Связь не может быть изменена, поскольку одно или несколько свойств внешнего ключа не могут быть обнулены"

Если я пытаюсь удалить "дочернюю" строку, я всегда получаю исключение. Вот снэпсет:

using (var context = new CompanyContext())
{
    ItemType itemType = context.ItemTypes.FirstOrDefault(i => i.Name == "ServerType");
    ItemTypeItem itemTypeItem = itemType.Items.FirstOrDefault(i => i.Name == "DatabaseServer");
    itemType.Items.Remove(itemTypeItem);
    context.SaveChanges(); <=== exception!
}

Следующее исключение выбрано для метода SaveChanges().

"Связь не может быть изменена, так как одно или несколько свойств внешнего ключа не имеют значения NULL. При изменении отношения к связанному свойству внешнего ключа устанавливается нулевое значение. -key не поддерживает нулевые значения, необходимо определить новое отношение, для свойства внешнего ключа должно быть назначено другое ненулевое значение, или не связанный с ним объект должен быть удален."

Конфигурация объектов

  public class ItemTypeConfiguration : NamedEntityConfiguration<ItemType>
  {
    public ConfigurationColumn ParentIDColumn;
    public ConfigurationColumn ValidationPatternColumn;
    public ItemTypeConfiguration() : base()
    {
      ParentIDColumn = new ConfigurationColumn() { Name = "ParentID", Ordinal = base.LastOrdinalPosition + 1 };
      ValidationPatternColumn = new ConfigurationColumn() { Name = "ValidationPattern", Length = 1024, Ordinal=base.LastOrdinalPosition + 2};
      this.Property(t => t.ParentID)
        .HasColumnName(ParentIDColumn.Name)
        .HasColumnOrder(ParentIDColumn.Ordinal);
      this.HasOptional(t => t.Parent).WithMany().HasForeignKey(u => u.ParentID).WillCascadeOnDelete(false);
      this.Property(t => t.ValidationPattern)
        .HasColumnName(ValidationPatternColumn.Name)
        .HasColumnOrder(ValidationPatternColumn.Ordinal)
        .HasMaxLength(ValidationPatternColumn.Length);
    }
...


  public class ItemTypeItemConfiguration : NamedEntityConfiguration<ItemTypeItem>
  {
    public ConfigurationColumn ItemTypeIDColumn;
    public ItemTypeItemConfiguration() : base()
    {
      ItemTypeIDColumn = new ConfigurationColumn(){Name="ItemTypeID", IsRequired=true, Ordinal= base.LastOrdinalPosition+1};
      this.Property(t => t.ItemTypeID)
        .HasColumnName(ItemTypeIDColumn.Name)
        .HasColumnOrder(ItemTypeIDColumn.Ordinal);
      this.HasRequired(t => t.ItemType).WithMany(t=>t.Items).HasForeignKey(u => u.ItemTypeID).WillCascadeOnDelete(true);
    }
...

enter image description here

Я нашел блог, но у меня нет метода DeleteObject.

http://blog.clicdata.com/2013/07/04/the-operation-failed-the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-properties-is-non-nullable/

Любые идеи? Спасибо.

Ответ 1

Вам нужно удалить ItemTypeItem. Невозможно просто удалить его из списка Items, поскольку он не может существовать сам по себе, потому что он имеет непутевой внешний ключ, ссылающийся на ItemType (ItemTypeID).

Чтобы удалить ItemTypeItem, добавьте

context.Entry(itemTypeItem).State = EntityState.Deleted;

Ответ 2

В инфраструктуре сущности 6.0, если вы удалите объект из основного контекстного набора, он будет работать. Например, чтобы удалить объект инвестиций, вы должны сделать следующее:

context.Investments.Remove(entity);
context.SaveChanges();

Это отличается от попытки удалить объект из его родителя/владельца, как показано ниже:

bankAccount.Investments.Remove(entity);
context.SaveChanges();

Это будет означать, что отношения не могут быть изменены исключением, указанным выше. Надеюсь, это поможет.

Ответ 3

В сущности 6.0 существует разница между:

context.Investments.Remove(entity);

и

context.Entry(entity).State = EntityState.Deleted;

При первом использовании каскадных удалений EF внутренне выполняет необходимые удаления дочерних коллекций. При использовании второго варианта EF не будет обрабатывать необходимые удаления, но позволяет обрабатывать переинтерфейцию/удаление этих дочерних объектов.

Ответ 4

Эта проблема возникает из-за того, что мы пытаемся удалить родительскую таблицу. Мы решаем проблему с помощью каскадного удаления.

В модели Создайте метод в классе dbcontext.

 modelBuilder.Entity<Job>()
                .HasMany<JobSportsMapping>(C => C.JobSportsMappings)
                .WithRequired(C => C.Job)
                .HasForeignKey(C => C.JobId).WillCascadeOnDelete(true);
            modelBuilder.Entity<Sport>()
                .HasMany<JobSportsMapping>(C => C.JobSportsMappings)
                  .WithRequired(C => C.Sport)
                  .HasForeignKey(C => C.SportId).WillCascadeOnDelete(true);

После этого в нашем вызове API

var JobList = Context.Job                       
          .Include(x => x.JobSportsMappings)                                     .ToList();
Context.Job.RemoveRange(JobList);
Context.SaveChanges();

Параметр удаления каскада удаляет родительскую, а также родительскую дочернюю таблицу с помощью этого простого кода. Попробуйте это простым способом.

Удалить диапазон, который используется для удаления списка записей в базе данных. Спасибо