3

如果我有一个具有许多条件的规则并且用户选择了多个条件,我如何编写一个 linq 查询,为我提供所有规则,其中该规则中的每个条件都与用户选择的条件一起存在?

这是我目前在 SQL 中的做法:

rule:
  ruleId int
  categoryId int

ruleCriteria:
  ruleId int,
  criteriaId int

@userCriteria:
  criteriaId int
  categoryId int

询问

SELECT
    r.ruleId
FROM dbo.rule r
INNER JOIN dbo.ruleCriteria rc ON r.ruleId= rc.ruleId
LEFT OUTER JOIN @userCriteria uc
        ON rc.criteriaId = uc.criteriaId
        AND r.categoryId = uc.categoryId
GROUP BY r.ruleId
HAVING COUNT(rc.criteriaId) = COUNT(uc.criteriaId)

对于 linq 查询,我将拥有这些对象(更加非规范化,但如果有帮助,我可以将它们放在与表相同的结构中):

userCriteria:
  criteriaId int
  categoryId int

ruleCriteria:
  ruleId int
  categoryId int
  criteriaId int

我的目标与获取不同匹配规则列表的 SQL 查询相同。你会怎么做?

4

3 回答 3

1

此查询生成的 SQL 比其他查询更好,而且更直接:

from rc in ruleCriterias
group rc by rc.ruleId into rules
where rules.All(rc => userCriterias.Any(uc =>
    uc.criteriaId == rc.criteriaId && uc.categoryId == rc.categoryId))
select rules.Key

您应该确保所有列都是NOT NULL,因为如果不是,则必须生成额外的 SQL 来检查是否为空。

于 2013-03-06T20:52:53.127 回答
1

我在LINQPad中使用了一些测试数据,这就是我想出的。

from rc in ruleCriteria
group new { rc.criteriaId, rc.categoryId } by rc.ruleId into rules
where rules.Count() == userCriteria.Count(uc =>
    rules.Contains(new { uc.criteriaId, uc.categoryId }))
select rules.Key

以下是逐行解释:

  1. 从中获取规则ruleCriteria
  2. { criteriaId, categoryId }将条件分组ruleId并保存在rules
  3. 对于每个完整的规则,检查匹配的userCriteria数量是否与规则的总数相同,这意味着用户具有所有条件。
  4. 仅选择该组的键,即ruleId.
于 2013-03-06T16:12:50.280 回答
0

除非我误解了(因此过于简单化了问题),否则 all .All()方法可能就是您所需要的。

var userCriteria = ; //TODO: Build user criteria
var result = context.Rules.Where(r => r.CategoryId == userCriteria.CategoryId
                                   && r.RuleCriteria.All(rc => rc.id == userCriteria.CriteriaId));

这只会返回所有包含条件都与您的条件匹配的规则。我不能保证你的 sql 虽然

于 2013-03-06T15:20:08.080 回答