mar*_*nes 5 .net c# entity-framework
我有以下两个班级:
public class Rule
{
public int Id { get; set; }
public string RuleValue { get; set; }
public bool IsActive { get; set; }
public SharedRuleType RuleType { get; set; }
public List<Exclusion> Exclusions { get; set; }
}
public class Exclusion
{
public int Id { get; set; }
public int InstanceId { get; set; }
public int SiteId { get; set; }
[ForeignKey( "RuleId" )]
public int RuleId { get; set; }
public Rule Rule { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个EF查询返回'all active' Rules,我需要它.Include Exclusionsfor each Rule(如果有的话)但只有Exclusions已经分配了指定的InstanceId.因此,过滤是针对Exclusions属性进行的,而不是过滤掉Rules.
在构建我需要考虑的EF查询时,我也有一些条件.
这是我目前的询问:
public async Task<List<Rule>> GetRules(int instanceId, SharedRuleType ruleType, string searchTerm)
{
using ( var context = new MyDbContext() )
{
var query = context.Set<Rule>()
.Include( r => r.Exclusions ) // *** Currently returns ALL exclusions but I only want ones where InstanceId == instanceId(param) ***
.Where( r => r.IsActive );
if ( !string.IsNullOrEmpty( searchTerm ) )
{
query = query.Where( r => r.RuleValue.Contains( searchTerm ) );
}
if ( ruleType != SharedRuleType.None )
{
query = query.Where( r => r.RuleType == ruleType );
}
return await query.ToListAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试在其中使用.Where .Include()试图仅包含相关Exclusions(基于instanceId)但发现你不能这样做.我在周围寻找,并找到了一些人们使用匿名类型的例子,但是当我在这里做的时候,我无法逐步建立查询.
所以,我不知道如何实现这个目标,因为我真的不希望每个人Exclusion都返回'每个' Rule,当我不需要每个人都Exclusion返回时.
Include 方法不能像您尝试的那样使用过滤器。
解决方案#1
免责声明:我是Entity Framework Plus项目的所有者
EF+ Query IncludeFilter 功能允许过滤相关实体。
public async Task<List<Rule>> GetRules(int instanceId, SharedRuleType ruleType, string searchTerm)
{
using ( var context = new MyDbContext() )
{
var query = context.Set<Rule>()
.IncludeFilter( r => r.Exclusions.Where(x => x.InstanceId == instanceId))
.Where( r => r.IsActive );
// ... code ...
Run Code Online (Sandbox Code Playgroud)
Wiki:EF+ 查询 IncludeFilter
解决方案#2
另一种技术是使用投影(这是我的图书馆在幕后所做的)
public async Task<List<Rule>> GetRules(int instanceId, SharedRuleType ruleType, string searchTerm)
{
using ( var context = new MyDbContext() )
{
var query = context.Set<Rule>()
.Where( r => r.IsActive );
if ( !string.IsNullOrEmpty( searchTerm ) )
{
query = query.Where( r => r.RuleValue.Contains( searchTerm ) );
}
if ( ruleType != SharedRuleType.None )
{
query = query.Where( r => r.RuleType == ruleType );
}
// ToListAsync has been removed to make the example easier to understand
return query.Select(x => new { Rule = x,
Exclusions = x.Exclusions.Where(e => e.InstanceId == instanceId)
})
.ToList()
.Select(x => x.Rule)
.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:回答子问题#1
如何在前面的示例中使用 ToListAsync
您只需等待第一个列表
return (await query.Select(x => new { Rule = x,
Exclusions = x.Exclusions.Where(e => e.InstanceId == instanceId)
})
.ToListAsync())
.Select(x => x.Rule)
.ToList();
Run Code Online (Sandbox Code Playgroud)
编辑:回答子问题#2
如何对规则执行 Skip、Take、OrderBy
你和平时一样
return (await query.Take(15)
.Skip(5)
.OrderBy(x => x.RuleId)
.Select(x => new { Rule = x,
Exclusions = x.Exclusions.Where(e => e.InstanceId == instanceId)
})
.ToListAsync())
.Select(x => x.Rule)
.ToList();
Run Code Online (Sandbox Code Playgroud)