1

我有一张桌子:

Groups
 - Id
 - Name
 - Type

此表是一组产品、客户或供应商。要对产品进行分组,我需要在 Type 列中使用“P”,要对客户和供应商进行分组,我需要分别使用“C”和“S”。

我想知道我是否可以在这里使用 TPH。就像创建一个包含除 Type 之外的所有字段的抽象类 Group,然后创建空子类 ProductGroup、ClientGroup 和 SupplierGroup,然后将 Type 列配置为具有值“P”、“C”和“S”的鉴别器以映射到它们各自类。

我尝试这样做,但是当 Group 类是抽象的或继承的类为空时,EF 似乎无法正确猜测我的意图。

我的课程如下:

abstract class Group {
    public int Id { get; set; }
    public string Name { get; set; }
}

class ProductGroup : Group
{}

// I did not create the other two classes yet.

我在 DbContext 中的配置如下:

public class DataContext : DbContext
{
    public DbSet<ProductGroup> ProductGroups { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new GroupConfiguration());
    }
}

class GroupConfiguration : EntityTypeConfiguration<Group>
{
    public GroupConfiguration()
    {
        Map<ProductGroup>(m =>
        {
            m.Requires("Type").HasValue("P");
        });
    }
}

我认为它应该可以工作,但是使用上面的代码,datacontext.ProductGroups 将返回所有组,而不仅仅是产品组。

我测试并发现如果我的 Group 类是具体的,代码将按我的预期工作,datacontext.ProductGroups 中的组将只是产品组。

我还测试并发现,如果我保留我的 Group 类抽象但移动 ProductGroup 类的字段“Name”,代码也将按预期工作。

我想知道这是一个错误,还是我走错了路。

我想出了这个想法,因为我的老板想要在我们的 web api 中使用一个端点“/productgroups”,我发现在系统中使用一个特定的产品组类会很有趣,而不是使用一个通用组和必须.Where(e => e.Type == "P")到处过滤。我认为在处理传递的对象时,后一种方法不太清楚。

有谁知道如何解决这个问题?我真的需要将我的 Group 课程具体化吗?我不喜欢它,Group 类似乎需要是抽象的,因为实际上我只有填充了 Type 字段的组。

4

3 回答 3

2

您缺少的是 EF 继承基于单个多态DbSet,而不同的策略(TPH、TPT 和 TPC)控制数据库内部的物理存储模型。

话虽如此,您需要以下内容DbContext(删除ProductGroups您到目前为止放置的内容):

public DbSet<Group> Groups { get; set; }

所有的 CRUD 操作都应该通过它DbSet。如果您需要特定的后代,则应该使用OfType方法。请注意,它可能会引入比使用具有显式Type属性的单个类更多的问题,因为 EF 不为您提供对鉴别器列的任何访问权限,因此在决定仅将其用于此目的之前请仔细考虑。

于 2017-01-18T12:24:22.023 回答
1

不确定这是否是问题,但我将映射放在 DbContext 的 OnModelCreating 方法中:

// Define DisplayLocation subclasses using discriminator column

modelBuilder.Entity<AbstractDisplayLocation>()
            .Map<VirtualDisplayLocation>(m => m.Requires("Virtual").HasValue(true))
            .Map<PdbLocation>(m => m.Requires("Virtual").HasValue(false));
于 2017-01-18T12:24:14.570 回答
0

我发现了问题。

我在代码的其他地方使用了 Group 类型。当我删除对 Group 类型的所有引用时,它起作用了!

谢谢你的所有答案

于 2017-01-18T12:30:20.580 回答