C# 建立EF查询时如何将WHERE条件应用于EF.Include()
我有以下两门课:C# 建立EF查询时如何将WHERE条件应用于EF.Include(),c#,.net,entity-framework,C#,.net,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 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; }
}
我尝试在.Include()
中应用.Where,试图只包含相关的排除项
(基于实例ID
),但发现您不能这样做。我四处寻找,发现了一些人们使用匿名类型的例子,但在我这里一块一块地构建查询时,我无法实现这一点
所以,我不知道如何才能做到这一点,因为我真的不想为每个
规则
返回'every'排除
,而我不需要返回每个排除
。编辑根据您的评论,您需要执行使表左连接的请求
这是您的新方法的变体
public class RuleModel
{
public Rule Rule { get; set; }
public IEnumerable<Exclusion> Exclusions { get; set; }
}
public async Task<List<RuleModel>> 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 );
}
// That statement do LEFT JOIN like:
// FROM Rules
// LEFT OUTER JOIN Exclusions ON ([Rules].[Id] = [Exclusions].[RuleId]) AND ([Exclusions].[InstanceId] = @instanceId)
var ruleExclusionQuery = query.Select(rule => new RuleModel { Rule = rule, Exclusions = rule.Exclusions.Where(e => e.InstanceId == instanceId) });
var ruleList = await ruleExclusionQuery.ToListAsync();
}
}
不再需要了。Include方法无法像您尝试的那样使用筛选器 解决方案#1 免责声明:我是项目的所有者 EF+查询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 ...
编辑:回答子问题#2
如何对规则执行跳过、执行、排序
你和平时一样
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();
条件包含
尚未由EF团队实施
这仍然是EF团队的工作项,您可以投票
请注意,当前无法筛选加载的相关实体。Include将始终引入所有相关实体。
如果要筛选include语句,需要使用EF上的投影
using ( var context = new MyDbContext() )
{
Expression<Func<Rules, bool>> whereCondition;
if (!string.IsNullOrEmpty( searchTerm ) )
{
whereCondition= x.RuleValue.Contains(searchTerm));
}
var query = context.Rules
.Where(whereCondition)
.Select(x=> new
{
rules = x,
exclustions = x.Exclusions.Where(secondCondition).ToList()
}.ToList();
}
有时候执行正确的SQL更容易。@VinodKumar不,还没有。我认为Vitaliy下面的解决方案不会起作用,因为它不会返回“全部”规则,它会根据排除情况过滤掉一些规则。有一次我在看这个。我模模糊糊地记得,我发现这是不可能的,但无法引用一个来源。也许最好通过SQL或单独的查询加载数据。在我的例子中,为满足条件的相关实体编写另一个查询是可以的。但是这不会过滤掉我的一些规则吗(只返回与实例匹配的排除规则)?我需要“所有”规则,不管它们是否有排除(以及它们是什么排除)。它只是需要过滤的包含的排除项(如果有)。@marcusstarnes我更新了代码。请检查它是否适合您。感谢您提供可能的解决方案。有一个问题,关于解决方案#2,我将如何将.Skip、.Take和.OrderBy合并到查询中,以便在一次到数据库的过程中执行过滤,因为事实证明我需要它。另外,我将如何使用wait/Async实现解决方案#2?您希望在哪个实体(规则或排除)上执行Skip、Take、OrderBy?规则。对于返回的每个规则,我总是希望“全部”过滤排除,但我可能一次只请求10条规则(为跳过和执行提供偏移量和限制)。如果这10条规则中的一条碰巧有50条过滤排除规则,我希望所有50条排除规则都适用。我还将传递一些东西(枚举)来标识要应用的请求排序顺序。谢谢,这正是我所需要的。
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();
}
}
return (await query.Select(x => new { Rule = x,
Exclusions = x.Exclusions.Where(e => e.InstanceId == instanceId)
})
.ToListAsync())
.Select(x => x.Rule)
.ToList();
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();
using ( var context = new MyDbContext() )
{
Expression<Func<Rules, bool>> whereCondition;
if (!string.IsNullOrEmpty( searchTerm ) )
{
whereCondition= x.RuleValue.Contains(searchTerm));
}
var query = context.Rules
.Where(whereCondition)
.Select(x=> new
{
rules = x,
exclustions = x.Exclusions.Where(secondCondition).ToList()
}.ToList();
}
if ( !string.IsNullOrEmpty( searchTerm ) )
{
whereCondition= x.RuleValue.Contains( searchTerm);
}
if ( ruleType != SharedRuleType.None )
{
whereCondition= x.RuleType ==ruleType;
}
//Ugly work around is
if ( !string.IsNullOrEmpty( searchTerm ) && ruleType != SharedRuleType.None)
{
whereCondition= x.RuleValue.Contains( searchTerm) && x.RuleType ==ruleType;
}