【问题标题】:What's the best way to go about reading and updating data in a Table-per-Type database model in Razor/EF Core?在 Razor/EF Core 的 Table-per-Type 数据库模型中读取和更新数据的最佳方法是什么?
【发布时间】:2025-11-22 01:15:02
【问题描述】:

我按照this guide 中概述的步骤为我的代码优先剃须刀应用程序设置了数据库。这一切都很好,但我不确定如何在我的应用程序中实际使用这个数据库结构。使用来自 t 的代码

public class PersonTpt
{
  public Guid Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Type { get; set; }
}

public class CustomerTpt
{
  [ForeignKey(nameof(Person))]
  public Guid Id { get; set; } // PK and FK pointing to PersonTpt
  public PersonTpt Person { get; set; }

  public DateTime DateOfBirth { get; set; }
}

public class EmployeeTpt
{
  [ForeignKey(nameof(Person))]
  public Guid Id { get; set; } // PK and FK pointing to PersonTpt
  public PersonTpt Person { get; set; }

  public decimal Turnover { get; set; }
}

在这种情况下,我已将“类型”字段添加到 PersonTpt 类。在实际应用程序中,我有一个“/Person/Edit”页面,其中包含用于编辑人员的表单,并且“Type”属性与选择列表相关联。该下拉列表将具有对应于 CustomerTpt 或 EmployeeTpt 的值,我希望表单根据所做的选择添加适当的字段。在我的数据库模型中,“Person”类只能有一个子类,并且会有大量子类(可能数百个),尽管我只展示了两个以保持示例简短

所以我有几个关于这一切的问题......

  1. 我将如何在编辑页面上实际使用此数据模型?我只需要为每个可能的子类创建一个局部视图吗?或者有没有办法将“变量”子类传递给页面模型?
  2. 在 EF Core 中是否有一种方法可以在自动检索子类时查询数据库中的“人员”(例如进行大型连接),或者我只需要对逻辑进行硬编码来获取子类基于什么类型是什么?在我链接的指南的示例中,它们只向后退,这更明显,因为那是链接所在的位置
  3. 我的一个想法是将类数据存储在字典对象(属性名称/值)中,但我认为我不能在表单中使用 razor TagHelpers,对(例如 asp-for、asp-验证等)?

【问题讨论】:

    标签: asp.net-core razor .net-core entity-framework-core razor-pages


    【解决方案1】:
    1. 我将如何在编辑页面上实际使用此数据模型?我只需要为每个可能的子类创建一个局部视图吗?或者有没有办法将“变量”子类传递给页面模型?

    你可以,但你也可以只检查类的类型并在必要时输出一些额外的 HTML 控件:

    if (person is CustomerTpt customer)
    {
        // Do something with customer here.
    }
    
    1. 在 EF Core 中是否有一种方法可以在自动检索子类时查询数据库中的“人员”(例如进行大型连接),或者我只需要对逻辑进行硬编码来获取子类基于什么类型是什么?在我链接的指南的示例中,它们只向后退,这更明显,因为那是链接所在的位置

    您也可以将导航属性添加到 PersonTpt 类:

    public class PersonTpt
    {
      public Guid Id { get; set; }
      public string FirstName { get; set; }
      public string LastName { get; set; }
      public string Type { get; set; }
    
      public CustomerTpt Customer { get; set; }
      public EmployeeTpt Employee { get; set; }
    }
    

    那么你可以按如下方式查询它们:

    var personsWithRelations = context.Persons
        .Include(p => p.Customer)
        .Include(p => p.Employee)
        .ToList();
    
    1. 我的一个想法是将类数据存储在字典对象(属性名称/值)中,但我认为我不能在表单中使用 razor TagHelpers,对(例如 asp-for、asp-验证等)?

    我不确定您的方法是什么。您可能需要提供一些代码(工作或不工作)来传达您的想法。

    【讨论】:

    • 对于您的第一点,这实际上是如何工作的?我不清楚代码将如何知道 Person 类是否“是”CustomerTpt 类。如果它那么简单,我可以尝试一下。对于第二点,这似乎是一个不错的可能性。但是假设我有 100 个不同的子类,我需要一个巨大的 if 语句来查看它实际上有哪一个,对吗?
    • 我不确定将代码放在评论中的最佳方式,因此我在单独的答案中回复了您的其他问题
    • 由于“子类”并不是真正的子类,因为它们不是从Person 继承的,所以我的示例中的person 变量要么需要是object 类型,要么您的所有子类都必须实现相同的接口,然后person 变量将属于该接口类型。然后,您可以使用is 运算符测试变量的实际类型(或使用新的Switch Expressions)。您也可以改用Strategy Pattern
    • 巨大的 if 语句或 switch 表达式将是实现这一点的一种方法。您还可以使用反射或使用方法实现接口,其中包含您要执行的子类特定算法。在后一种情况下,您不需要知道您正在处理的子类。 (当这些类实际上是从 Person 派生时,也会出现这个问题,而不仅仅是您的 TPT 模拟案例。)
    • 不要用另一个问题来回答你的问题。如果其他答案不令人满意,请永远回答您自己的问题,或者通过编辑添加到您的初始问题中。
    最近更新 更多