我有一张桌子:
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字段的组。
答案 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类型的所有引用时,它工作了!
感谢您提供所有答案