从对基础的请求中排除派生实体 class
Exclude derived entities from requests to the base class
我有这个 DbContext:
public class DataContext : DbContext
{
public DbSet<Base> Bases {get;set}
public DbSet<Sub> Subs {get;set}
}
Sub
是 Base
的子类。
当我像这样查询基本实体列表时:
Context.Bases.ToListAsync()
它 returns 我每个实体,Base
或 Sub
。
如何配置我的模型上下文以仅获取 Base
类型的实体,而不是从它派生的实体。
How can I configure my model context to get only the entities that are
of Base type and not the ones that derives from it.
你不能。每个 Sub 是 一个 Base。因此查询所有 Bases 包括所有 Subs。例如像下面这样的代码必须成功:
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
您可以获取仅具有基本 class 属性的匿名类型。
问这个问题表明继承可能不是适合您的场景的正确建模技术。
如果您希望它获取 Base 类型的实体,但 不是 子类型 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,会在客户端过滤掉子类型。
你必须使用 OfType<T>
:
var basesOnly = await _context.Bases.OfType<Base>().ToListAsync();
更新
那么抱歉。我本可以发誓上述作品,但事实并非如此。我能想到的下一个最佳方法是简单地过滤掉不需要的类型。这并不理想,因为它需要在您的查询中指定所有子类型,这意味着如果您添加更多子类型,您需要记得更新它。
var basesOnly = await _context.Bases.Where(x => !(x is Sub)).ToListAsync();
我找到的最好(或最差)的解决方案是直接使用阴影 属性:
Context.Bases.Where(b => EF.Property<string>(b, "Discriminator") == "Base")).ToListAsync();
它有效,但需要不时重复,每次我需要查询 Bases
。我更喜欢 OnModelCreating
方法中的解决方案。
除非其他人找到更好的解决方案,否则我会接受这个答案。
我有这个 DbContext:
public class DataContext : DbContext
{
public DbSet<Base> Bases {get;set}
public DbSet<Sub> Subs {get;set}
}
Sub
是 Base
的子类。
当我像这样查询基本实体列表时:
Context.Bases.ToListAsync()
它 returns 我每个实体,Base
或 Sub
。
如何配置我的模型上下文以仅获取 Base
类型的实体,而不是从它派生的实体。
How can I configure my model context to get only the entities that are of Base type and not the ones that derives from it.
你不能。每个 Sub 是 一个 Base。因此查询所有 Bases 包括所有 Subs。例如像下面这样的代码必须成功:
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
您可以获取仅具有基本 class 属性的匿名类型。
问这个问题表明继承可能不是适合您的场景的正确建模技术。
如果您希望它获取 Base 类型的实体,但 不是 子类型 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,会在客户端过滤掉子类型。
你必须使用 OfType<T>
:
var basesOnly = await _context.Bases.OfType<Base>().ToListAsync();
更新
那么抱歉。我本可以发誓上述作品,但事实并非如此。我能想到的下一个最佳方法是简单地过滤掉不需要的类型。这并不理想,因为它需要在您的查询中指定所有子类型,这意味着如果您添加更多子类型,您需要记得更新它。
var basesOnly = await _context.Bases.Where(x => !(x is Sub)).ToListAsync();
我找到的最好(或最差)的解决方案是直接使用阴影 属性:
Context.Bases.Where(b => EF.Property<string>(b, "Discriminator") == "Base")).ToListAsync();
它有效,但需要不时重复,每次我需要查询 Bases
。我更喜欢 OnModelCreating
方法中的解决方案。
除非其他人找到更好的解决方案,否则我会接受这个答案。