实体框架TPH更改抽象基类中的鉴别器列和空的继承类方案

时间:2017-01-18 11:55:10

标签: c# entity-framework tph

我有一张桌子:

Groups
 - Id
 - Name
 - Type

此表是一组产品,客户或供应商。要对我需要使用的产品进行分组" P"在“类型”列中,对于组客户端和供应商,我需要使用" C"和" S" respectivelly。

我想知道我是否可以在这里使用TPH。就像创建一个包含Type但所有字段的抽象类Group一样,然后创建空子类ProductGroup,ClientGroup和SupplierGroup,然后将Type列配置为具有值" P"," C&#34的鉴别器;和" 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类抽象但移动字段&#34; Name&#34;对于ProductGroup类,代码也将按预期工作。

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

我提出了这个想法,因为我的老板想要一个端点&#34; / productgroups&#34;在我们的web api中,我发现在系统中使用特定的产品组类会很有趣,而不是使用通用组,并且必须在任何地方过滤.Where(e => e.Type == "P")。我认为后一种方法在处理传递的物体时不太清楚。

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

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分: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));

答案 2 :(得分:0)

我发现了这个问题。

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

感谢您提供所有答案