Объекты EF Core TPH с тем же требуемым типом свойства вызывают исключение «Введение ограничения ВНЕШНЕГО КЛЮЧА»

#.net #foreign-keys #entity-framework-core

#.net #внешние ключи #entity-framework-core

Вопрос:

У меня есть два класса, которые являются производными от одного и того же базового класса и имеют одинаковое требуемое свойство. Они находятся в одной таблице (TPH).

Когда я пытаюсь создать базу данных, я получаю это исключение:

System.Data.SqlClient.SQLException : Введение ограничения ВНЕШНЕГО КЛЮЧА ‘FK_As_Bs_A2BId’ в таблицу ‘As’ может вызвать циклы или несколько каскадных путей. Укажите, что ПРИ УДАЛЕНИИ НЕТ ДЕЙСТВИЯ или ПРИ ОБНОВЛЕНИИ НЕТ ДЕЙСТВИЯ, или измените другие ограничения ВНЕШНЕГО КЛЮЧА. Не удалось создать ограничение или индекс. Смотрите предыдущие ошибки.

 public class Entity
{
    public long Id { get; set; }
}

public abstract class A : Entity { }

public class A1 : A
{
    [Required]
    public B A1B { get; set; }
}

public class A2 : A
{
    [Required]
    public B A2B { get; set; }
}

public class B : Entity { }

public class MyContext : DbContext
{
    public MyContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<A> As { get; set; }
    public DbSet<A1> A1s { get; set; }
    public DbSet<A2> A2s { get; set; }
    public DbSet<B> Bs { get; set; }
}

public class CreateDbTests
{
    [Fact]
    public void CreateDb()
    {
        var optionsBuilder = new DbContextOptionsBuilder();

        optionsBuilder.UseSqlServer("YOURCONNECTIONSTRING");
        using (var context = new MyContext(optionsBuilder.Options))
        {
            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();
        }
    }
}
  

Кто-нибудь может объяснить мне проблему? Я этого не понимаю. Можно подумать, что это ошибка.
Проблема возникает только тогда, когда свойство обоих объектов имеет требуемый атрибут и оба находятся в одной таблице (TBH). Нет проблем, когда A1 и A2 получают свои собственные таблицы (не добавляя DbSet<A> ).

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

1. Чем больше я думаю об этом, тем больше мне кажется, что это ошибка. Итак, я создал проблему .

Ответ №1:

Это не ошибка, а ограничение базы данных SQLServer (и некоторых других). Это происходит, когда одна таблица имеет более одной каскадной FK-связи с другой таблицей.

В вашем случае это вызвано TPH, но то же самое произойдет, если у вас есть

 public class C : Entity
{
    [Required]
    public B C1B { get; set; }
    [Required]
    public B C2B { get; set; }
}
  

TPH использует единую таблицу для хранения всех производных объектов, следовательно, на все одной таблице наложены ограничения на отношения FK.

Чтобы решить проблему в обоих случаях, вам необходимо разорвать «каскадную» часть «множественных каскадных путей», отключив каскадное удаление по крайней мере для одной из задействованных взаимосвязей и обработать удаление вручную или с помощью триггера базы данных.