Ограничение внешнего ключа при наличии свойства навигации к производному классу - PullRequest
2 голосов
/ 26 июня 2019

Я использую code-first для создания своих баз данных в Entity Framework и использую подход «Таблица на иерархию» для иерархии наследования для класса, показанного ниже.

Когда я запускаю миграцию, все работает, но когда я обновляю свою базу данных, я получаю следующую ошибку:

System.Data.SqlClient.SqlException: оператор INSERT конфликтует с FOREIGNКЛЮЧЕВОЕ ограничение "FK_dbo.BaseStatus_dbo.Rider_ID".Конфликт произошел в базе данных «ASPNET_INSURANCE_c48b7267b7cd4bac952caa1a467ab9ae», таблица «dbo.Rider», столбец «ID».

У меня есть класс, который имеет свойство навигации для производного класса.(Упрощенный код)

    public class Rider
    {
       public int ID { get; set; }
       public virtual DerivedStatus derivedStatus { get; set; }
    }

Производные классы с аннотациями данных выглядят так:

    public class BaseStatus
    {
        [Key, ForeignKey("rider")]
        public int ID { get; set; }

        public bool? Married { get; set; }

        public virtual Rider rider { get; set; }
    }

    public class DerivedStatus : BaseStatus
    {
        public bool? HomeOwnership { get; set; }
    }

Для DbContext я только что добавил следующее, чтобы создать таблицу, которая работает должным образом (все свойства в одной таблице со столбцом Дискриминатор).

public DbSet<BaseStatus> Status { get; set; }

Отношения между Rider и производным классом взаимно однозначные.

Я не уверен, что это уместно / поможет, но ниже приведена часть DbMigrationфайл, который генерируется:

                CreateTable(
                "dbo.Rider",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        CorrelationID = c.Guid(),
                        derivedStatus_ID = c.Int(),
                    })
                .PrimaryKey(t => t.ID)
                .ForeignKey("dbo.BaseStatus", t => t.derivedStatus_ID)
                .Index(t => t.derivedStatus_ID);

При обновлении базы данных я также заполняю ее некоторыми тестовыми данными, которые, как я полагаю, возникают при обнаружении этой проблемы.

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

В дальнейшем, вероятно, будут и другие производные классы классов BaseStatus и Rider, причем различные производные Riders будут использовать разные классы Status, поэтому любое решение должно быть масштабируемым.Может случиться так, что когда проект будет расти, я перейду с Таблицы для Иерархии на Таблицу для Типа, но сейчас мне нужно решение для TPH (если это возможно)

Ответы [ 2 ]

0 голосов
/ 28 июня 2019

Я наконец нашел ответ !!

Отчасти проблема заключалась в том, что я не знал фразу того, что пытался выполнить, поэтому затруднялся поиск ответов.Если вы пытаетесь достичь того же, что и я, вам нужна фраза Полиморфные ассоциации .Наконец-то я нашел то, что искал в этой статье здесь .

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

    public class Rider
    {
       public int ID { get; set; }
       public virtual DerivedStatus derivedStatus { get; set; }
    }

    public class BaseStatus
    {
        [Key]
        public int ID { get; set; }

        public bool? Married { get; set; }

    }

    public class DerivedStatus : BaseStatus
    {
        public bool? HomeOwnership { get; set; }
    }

DbContext остается таким же, какдо.Протестировав это, это также работает для TPT, вам просто нужно добавить аннотации данных для создания отдельных таблиц Entity.

ОБНОВЛЕНИЕ: После еще одного тестирования я обнаружил, что вы можете использовать внешний ключ и навигационные свойства в базовом классе, но вам нужно дополнить аннотации данных Fluent API, поскольку я не могу их получить.работать самостоятельно.Я использовал Fleunt API:

modelBuilder.Entity<BaseStatus>()
                .HasRequired(e => e.Rider)
                .WithOptional(e => e.DerivedStatus)
                .WillCascadeOnDelete(true);
0 голосов
/ 26 июня 2019

проверить значения в таблице. Являются ли эти значения действительными (следуйте ограничениям внешнего ключа)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...