【问题标题】:Is it possible for Inheritance 2 child class to have reference to the same property?Inheritance 2 子类是否可以引用相同的属性?
【发布时间】:2019-06-08 18:35:04
【问题描述】:

我正在尝试使用 EF Core 设计数据模型。

我有一个 InformalOranization LegalOrganization 和 Person 继承自的 Party 类(超类)。只有 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”中。 声明已终止。

【问题讨论】:

  • 您可以添加另一个派生自Party 并包含成员TaxIdentificationNumber 的类。 PersonLegalOrganization 然后派生自这个附加类。
  • 好吧,根据你的例子,它应该在抽象类中,因为它是一个公共属性
  • @noox 我只是编辑 LegalOrganization 类。它继承自组织。并非所有组织都应纳税。非正式组织(未经注册)不是。因此,LegalOrganization 源于组织。并且 InformalOrganization (that) 在这个问题上并不重要,也继承自 Organization,并且不征税。
  • 我假设您在 Organization 中也有字段。如果没有:你真的需要它吗?否则我不知道一个好的解决方案。您可以在Party 中使用TaskIdentifiacationNumber,但也可以在InformalOrganizations 中使用。或者两个派生类中的两个不同名称的 TaxIdentifactionNumber。
  • 我刚刚偶然发现了支持字段 (docs.microsoft.com/en-us/ef/core/modeling/backing-field)。也许您可以在Party 中添加一个受保护字段_taxIdentIficationNumber,将其定义为支持字段,并仅在PersonLegalOrganization 中公开具有公共属性的受保护字段。但我没有尝试过,它肯定不完美。

标签: c# .net sql-server entity-framework-core


【解决方案1】:

您可以使用interface

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

然后你可以让PersonLegalOrganization继承它:

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

【讨论】:

    【解决方案2】:

    添加TaxIdentificationNumber 类的实现后,现在很清楚它应该如何工作以及问题所在。 PersonLegalOrganization 中的 TaxIdentificationNumber 只能是使用 TaxIdentificationNumber 中的 PartyId 作为外键的参考导航属性。

    当我在 EF Core 2.2.4 中为此模型创建数据库时,我没有收到错误消息。但结果不是你想要的。 TaxIdentificationNumber 中的 Party 属性属于 Party 类型,但另一方面,您有 PersonLegalOrganization 类型。因此 EF 与它们不匹配,它为 PersonLegalOrganization 中的 TaxIdentificationNumber 创建外键,它们都以 Parties 表结尾:

    我尝试使用流畅的 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 分配给TaxIdentificationNumber 中的Party 属性(而不是Person)。对于Person,在Parties-Table 中创建了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 分配给TaxIdentificationNumberParty 属性。

    最简单的解决方法是将引用导航属性 TaxIdentificationNumberPersonLegalOrganization 添加到 Party 类。使用这种方法,更容易错误地将TaxIdentifactionNumber 分配给InformalOrganization。您可以使用 Discriminator 列添加数据库 CHECK CONSTRAINT 以防止在数据库级别发生这种情况。

    另一种方法是使用两个外键。一种用于Person,另一种用于LegalOrganization。但这似乎更难看。

    【讨论】:

    • 是的@noox。我仍在努力解决这个问题。我现在没有解决方案,直到现在没有人提出解决方案。我目前正在Party 中使用TaxIdentifactionNumber,同时寻求解决方案。
    猜你喜欢
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多