Ошибка самоссылки в ядре EF: оператор insert конфликтовал с ограничением таблицы с тем же внешним ключом

#c# #sql-server #entity-framework-core

#c# #sql-сервер #entity-framework-core

Вопрос:

У меня есть Category модель с самоссылкой, и она отлично работала при создании базы данных, но когда я пытаюсь вставить родительскую категорию (объект без родительского идентификатора), я получаю ошибку, указывающую на родительский идентификатор внешнего ключа, но она отлично работает, когда я вставляю topel вручную с помощью скрипта insert в SSMS, и отлично работает с ядром ef при добавлении подкатегории (объекта, у которого есть родительский идентификатор).

Модель категории

 public class Category : ICategory
{
    public Category()
    {
    }

    [Key]
    public int Id { get; set; }

    [Required]
    [MinLength(2)]
    [MaxLength(32)]
    public string Title { get; set; }

    public string Icon { get; set; }

    [DefaultValue(true)]
    public bool IsEnabled { get; set; }

    [Required]
    public DateTime CreateTimeStamp { get; set; }

    public DateTime LastUpdateTimeStamp { get; set; }

    [ForeignKey("User")]
    public int CreatorUserId { get; set; }
    
    public int? ParentId { get; set; }

    public virtual User User { get; set; }
    
    [ForeignKey("ParentId")]
    public virtual Category Parent { get; set; }
    public virtual ICollection<Category> Children { get; set; }
    public virtual ICollection<Service> Services { get; set; }
}
  

DbContext

 public DbSet<Category> Categories { get; set; }

modelBuilder.Entity<Category>(entity =>
        {
            entity.HasIndex(e => e.Title).IsUnique();
            entity.HasOne(e => e.User).WithMany(e => e.CreatedCategories)
                .HasForeignKey(e => e.CreatorUserId).OnDelete(DeleteBehavior.Restrict);
            entity.HasOne(e => e.Parent).WithMany(e => e.Children).HasForeignKey(e => e.ParentId).IsRequired(false);
        });
  

Миграция

 protected override void Up(MigrationBuilder migrationBuilder)
{
        migrationBuilder.CreateTable(
            name: "Categories",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Title = table.Column<string>(maxLength: 32, nullable: false),
                Photo = table.Column<string>(nullable: true),
                IsEnabled = table.Column<bool>(nullable: false),
                CreateTimeStamp = table.Column<DateTime>(nullable: false),
                LastUpdateTimeStamp = table.Column<DateTime>(nullable: false),
                CreatorUserId = table.Column<int>(nullable: false),
                ParentId = table.Column<int>(nullable: true)
            }
            constraints: table =>
            {
                table.PrimaryKey("PK_Categories", x => x.Id);
                table.ForeignKey(
                    name: "FK_Categories_Users_CreatorUserId",
                    column: x => x.CreatorUserId,
                    principalTable: "Users",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_Categories_Categories_ParentId",
                    column: x => x.ParentId,
                    principalTable: "Categories",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });
}
  

Я все равно пометил «ParentID» как обнуляемый, но ef core мне мешает, хотя SQL Server с этим в порядке!

Сообщение об ошибке внутреннее исключение:

Оператор INSERT конфликтовал с ограничением таблицы с ТЕМ же ВНЕШНИМ КЛЮЧОМ «FK_Categories_Categories_ParentId». Конфликт произошел в базе данных «Unknown_Db», таблица «dbo.Категории», столбец ‘Id’.

Комментарии:

1. Можете ли вы добавить сообщение об ошибке?

2. Какую версию C # и EFC вы используете?

3. Можете ли вы включить журнал команд ядра EF? Добавление новой категории с помощью Parent = null и ParentId = null должно сработать, поэтому в модели / конфигурации примера чего-то должно не хватать, или база данных отличается от указанной при переносе.

4. можете ли вы показать внешний ключ, который также создавался при миграции? Какое ссылочное действие использует FK? Это должно выглядеть примерно так: table.ForeignKey(name: "FK_Categories_Categories_ParentId", column: x => x.ParentId, principalTable: "Categories", principalColumn: "Id", onDelete: ReferentialAction.Restrict);

5. @Omid На скриншоте показано, что это ParenId равно 0 нулю), что не совпадает с null и, скорее всего, вызывает ошибку.

Ответ №1:

Попробуйте это, когда вы обрабатываете входные значения:

 if (category.ParentId == 0)
{
    category.ParentId = null;
}