Возможно ли, чтобы дочерний класс Inheritance 2 имел ссылку на одно и то же свойство? - PullRequest
0 голосов
/ 08 июня 2019

Я пытаюсь спроектировать модель данных, используя EF Core.

У меня есть класс Party (суперкласс), от которого наследуются InformalOranization LegalOrganization и Person. Только у LegalOrganization и Person есть TaxNumber. Таким образом, эти 2 класса имеют свойство класса TaxNumber.

public abstract class Party
{
    public Party()
    {
        Names = new List<Name>();
    }

    public int PartyId { get; set; }

    public PartyType PartyType { get; set; }

    public string Comment { get; set; }

}



public class Person : Party
{
    public Person()
    {

    }

    public Gender Gender { get; set; }

    public DateTime Birthday { get; set; }

    public TaxIdentificationNumber TaxIdentificationNumber { get; set; }

}

public class LegalOrganization : Organization
{
    public LegalOrganization()
    {
    }

    public DateTime RegistrationDate { get; set; }

    public bool IsProfitable { get; set; }

    public TaxIdentificationNumber TaxIdentificationNumber { get; set; }

}


public class TaxIdentificationNumber
{
    public int TaxIdentificationNumberId { get; set; }

    public string Number { get; set; }

    public DateTime IssueDate { get; set; }

    public int PartyId { get; set; }

    public Party Party { get; set; }

}

Я получаю эту ошибку.

Необработанное исключение: Microsoft.EntityFrameworkCore.DbUpdateException: при обновлении записей произошла ошибка. Смотрите внутреннее исключение для деталей. ---> System.Data.SqlClient.SqlException: инструкция MERGE конфликтует с ограничением FOREIGN KEY "FK_TaxIdentificationNumbers_Parties_PartyId". Конфликт произошел в базе данных "Teknowhow.DataModel080519_01", таблице "dbo.Parties", столбце "PartyId". Заявление было прекращено.

Ответы [ 2 ]

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

После того, как вы добавили реализацию класса TaxIdentificationNumber, теперь понятно, как он должен работать и в чем проблема. TaxIdentificationNumber in Person и LegalOrganization должны быть только ссылочными навигационными свойствами, используя PartyId in TaxIdentificationNumber в качестве внешнего ключа.

Когда я создаю базу данных для этой модели в EF Core 2.2.4, я не получаю сообщение об ошибке. Но результат не то, что вы хотите. Свойство Party в TaxIdentificationNumber имеет тип Party, но с другой стороны у вас есть типы Person и LegalOrganization. Таким образом, EF не соответствует им и создает внешние ключи для TaxIdentificationNumber в Person и LegalOrganization, которые оба заканчиваются в таблице Parties:

enter image description here

Я пытался использовать свободный API:

        modelBuilder.Entity<Person>()
            .HasOne(p => p.TaxIdentificationNumber)
            .WithOne(t => (Person)t.Party)
            .HasForeignKey<TaxIdentificationNumber>(t => t.PartyId);

        modelBuilder.Entity<LegalOrganization>()
            .HasOne(l => l.TaxIdentificationNumber)
            .WithOne(t => (LegalOrganization)t.Party)
            .HasForeignKey<TaxIdentificationNumber>(t => t.PartyId);

Но здесь, похоже, вторая победа. Когда я хотел добавить данные, я мог только назначить LegalOrganization свойству Party в TaxIdentificationNumber (не Person). А для Person был создан TexIdentifactionNumberId в таблице сторон.

Когда я еще конкретнее

        modelBuilder.Entity<Person>()
            .HasOne(p => p.TaxIdentificationNumber)
            .WithOne(t => (Person)t.Party)
            .HasForeignKey<TaxIdentificationNumber>(t => t.PartyId)
            .HasPrincipalKey<Party>(t => t.PartyId);

        modelBuilder.Entity<LegalOrganization>()
            .HasOne(l => l.TaxIdentificationNumber)
            .WithOne(t => (LegalOrganization)t.Party)
            .HasForeignKey<TaxIdentificationNumber>(t => t.PartyId)
            .HasPrincipalKey<Party>(p => p.PartyId);

Я получаю эту ошибку:

Вы настраиваете связь между TaxIdentificationNumber и Person, но указали внешний ключ, нацеленный на «Party». Внешний ключ должен быть ориентирован на тип, который является частью отношения.

Так что я предполагаю, что EF не допускает такую ​​модель. Я думаю, что не легко создать модель, которая ведет себя так, как вы хотите, и вполне разумна. У вашей модели есть недостаток: вы можете присвоить InformalOrganization свойству Party TaxIdentificationNumber.

Самый простой обходной путь - добавить свойство ссылочной навигации TaxIdentificationNumber из Person и LegalOrganization в класс Party. При таком подходе еще проще ошибочно назначить TaxIdentifactionNumber на InformalOrganization. Вы можете добавить базу данных CHECK CONSTRAINT со столбцом Discriminator, чтобы предотвратить это на уровне базы данных.

Еще один вариант - работа с двумя внешними ключами. Один для Person и один для LegalOrganization. Но это кажется еще страшнее.

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

Вы можете использовать интерфейс :

public interface Taxable
{
    public TaxIdentificationNumber TaxIdentificationNumber { get; set; }
}

Тогда вы можете заставить Person и LegalOrganization наследовать от него:

public class Person : Party, Taxable
{
    // etc.
}
public class LegalOrganization: Party, Taxable
{
    // etc.
}
...