从请求到基类中排除派生实体

时间:2018-10-30 11:38:46

标签: entity-framework asp.net-core ef-core-2.0

我有这个DbContext:

public class DataContext : DbContext
{
    public DbSet<Base> Bases {get;set}
    public DbSet<Sub> Subs {get;set}
}

SubBase的子类。

当我像这样查询基本实体列表时:

Context.Bases.ToListAsync()

它返回我每个实体,BaseSub

如何配置我的模型上下文,使其仅获取Base类型的实体,而不从其派生的实体。

3 个答案:

答案 0 :(得分:1)

  

如何配置我的模型上下文以仅获取以下实体   基本类型,而不是其基础类型。

您不能。每个Sub 都是一个基础。因此,查询所有库都包括所有子库。像下面这样的代码必须成功:

Base b = db.Bases.Where(i => i.Id == 1).Single();
if (b is Sub)
begin
  Sub s = (Sub)b;
  . . .
end
else //other Sub
begin
  Sub2 s = (Sub2)b;
  . . .

end

您可以仅使用基类属性来获取匿名类型。

问这个问题建议,继承可能不是适合您的方案的建模技术。

如果您希望它获取Base类型的实体,而Sub类型不是Sub的 ,则可以使用以下查询来做到这一点:

var q = from b in db.Bases
        where !(b is Sub)
        select b;

翻译为:

SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[Size]
FROM [Bases] AS [b]
WHERE [b].[Discriminator] IN (N'Sub', N'Base') 
AND NOT ([b].[Discriminator] = N'Sub')

但是(当前)您不能(如果没有)枚举所有子类型。例如此查询:

var q2 = from b in db.Bases
         where b.GetType() == typeof(Base)
         select b;

不会完全转换为SQL,并且会过滤掉客户端上的子类型。

答案 1 :(得分:1)

您必须使用OfType<T>

var basesOnly = await _context.Bases.OfType<Base>().ToListAsync();

更新

那么,很抱歉。我本可以宣誓以上作品,但事实并非如此。我能想到的下一个最佳方法是简单地过滤掉不需要的类型。这不是理想的,因为它需要在查询中指定所有子类型,这意味着如果您添加更多子类型,则需要记住对其进行更新。

var basesOnly = await _context.Bases.Where(x => !(x is Sub)).ToListAsync();

答案 2 :(得分:1)

我发现最好的(或最差的)解决方案是直接使用shadow属性:

Context.Bases.Where(b => EF.Property<string>(b, "Discriminator") == "Base")).ToListAsync();

它可以工作,但是每次我需要查询Bases时,都需要不时重复。我本来希望使用OnModelCreating方法中的解决方案。

除非有人找到更好的解决方案,否则我会接受这个答案。