按具有布尔值 属性 的对象 属性 过滤
Filtering by object property that has a boolean property
我有以下对象:
public class Item
{
public int Id {get; set;}
public Process Process {get; set;}
}
public class Process
{
public bool Alive {get; set;}
}
我正在尝试这样做:
context.DB.Items
.Include(x => x.Process)
.Where(x => x.Process.Alive);
但是过滤总是让我得到 Process.Alive 为假的项目。
按 属性 过滤的最佳方法是什么,该 属性 包含在作为主要项目的 属性 的对象中?
借助 EF Core,您可以对 one-off 查询使用筛选的 Include
:
context.DB.Items
.Include(x => x.Process
.Where(x => x.Process.Alive));
或使用全局查询过滤器告诉 EF 只获取“有效”记录:
https://docs.microsoft.com/en-us/ef/core/querying/filters
对于 EF6,使用 Include
预加载集合表示该实体的完整数据状态。过滤后的包含可能会产生误导,因为它们不一定代表任何给定时间点的数据域状态的完整图片。
如果您通常只想处理活动行,例如查看结果等,则可以通过投影进行管理。例如,如果我有一个视图,我想在其中显示一个项目及其进程,我将有一个 ItemViewModel 和一个 ProcessViewModels 集合,只显示我的视图关心的数据。当我投射那个视图模型时:
var item = context.Items
.Select(x => new ItemViewModel
{
ItemId = x.ItemId,
// ....
Processes = x.Processes
.Where(x => x.Alive)
.Select(p => new ProcessViewModel
{
ProcessId = p.ProcessId,
// ...
}).ToList()
}).Single(x => x.ItemId == itemId);
这可以使用 Automapper 和它的 ProjectTo
方法进行简化和集中,这样您就可以配置 Automapper 映射以遵循“活动”活动状态,然后您的查询就像:
var item = context.Items
.ProjectTo<ItemViewModel>(config)
.Single(x => x.ItemId == itemId);
其中“config”是一个 MapperConfiguration,其中包含有关如何将 Item 映射到 ItemViewModel 以及将 Process 映射到 ProcessViewModel 的详细信息。 Automapper 负责剩下的工作,将必要的细节投射到 EF 中以生成合适的 SQL 语句。
如果您确实想使用实体来执行更新和引用详细信息,那么您可以投影一个匿名类型:
var itemsAndAliveProcesses = context.Db.Items
.Select(x => new
{
Item = x,
AliveProcesses = x.Processes.Where(p => p.Alive).ToList()
}).Single(x => x.ItemId == itemId);
在这里您可以使用 itemsAndAliveProcesses.AliveProcesses 来访问该项目的活动进程,而不是 .Item.Processes 如果您可以将其留给 lazy-load 或 eager-load确实想访问整个集合。
我建议投影优于过滤 Include
,因为利用投影会导致比加载整个实体图更有效的查询,并且它有助于确保当您使用实体图时,这些方法可以始终如一地期望接收数据状态的完整或可完成的表示。 (而不是过滤子集,因为您可以在 任何东西 上过滤 Include
)
我有以下对象:
public class Item
{
public int Id {get; set;}
public Process Process {get; set;}
}
public class Process
{
public bool Alive {get; set;}
}
我正在尝试这样做:
context.DB.Items
.Include(x => x.Process)
.Where(x => x.Process.Alive);
但是过滤总是让我得到 Process.Alive 为假的项目。
按 属性 过滤的最佳方法是什么,该 属性 包含在作为主要项目的 属性 的对象中?
借助 EF Core,您可以对 one-off 查询使用筛选的 Include
:
context.DB.Items
.Include(x => x.Process
.Where(x => x.Process.Alive));
或使用全局查询过滤器告诉 EF 只获取“有效”记录:
https://docs.microsoft.com/en-us/ef/core/querying/filters
对于 EF6,使用 Include
预加载集合表示该实体的完整数据状态。过滤后的包含可能会产生误导,因为它们不一定代表任何给定时间点的数据域状态的完整图片。
如果您通常只想处理活动行,例如查看结果等,则可以通过投影进行管理。例如,如果我有一个视图,我想在其中显示一个项目及其进程,我将有一个 ItemViewModel 和一个 ProcessViewModels 集合,只显示我的视图关心的数据。当我投射那个视图模型时:
var item = context.Items
.Select(x => new ItemViewModel
{
ItemId = x.ItemId,
// ....
Processes = x.Processes
.Where(x => x.Alive)
.Select(p => new ProcessViewModel
{
ProcessId = p.ProcessId,
// ...
}).ToList()
}).Single(x => x.ItemId == itemId);
这可以使用 Automapper 和它的 ProjectTo
方法进行简化和集中,这样您就可以配置 Automapper 映射以遵循“活动”活动状态,然后您的查询就像:
var item = context.Items
.ProjectTo<ItemViewModel>(config)
.Single(x => x.ItemId == itemId);
其中“config”是一个 MapperConfiguration,其中包含有关如何将 Item 映射到 ItemViewModel 以及将 Process 映射到 ProcessViewModel 的详细信息。 Automapper 负责剩下的工作,将必要的细节投射到 EF 中以生成合适的 SQL 语句。
如果您确实想使用实体来执行更新和引用详细信息,那么您可以投影一个匿名类型:
var itemsAndAliveProcesses = context.Db.Items
.Select(x => new
{
Item = x,
AliveProcesses = x.Processes.Where(p => p.Alive).ToList()
}).Single(x => x.ItemId == itemId);
在这里您可以使用 itemsAndAliveProcesses.AliveProcesses 来访问该项目的活动进程,而不是 .Item.Processes 如果您可以将其留给 lazy-load 或 eager-load确实想访问整个集合。
我建议投影优于过滤 Include
,因为利用投影会导致比加载整个实体图更有效的查询,并且它有助于确保当您使用实体图时,这些方法可以始终如一地期望接收数据状态的完整或可完成的表示。 (而不是过滤子集,因为您可以在 任何东西 上过滤 Include
)