我该如何编写这个LINQ查询

时间:2016-10-31 14:59:44

标签: c# linq

这是我正在尝试做的事情:

我有一组记录。记录按年份排序。

Record
{
  string Name {get;set;},
  int Year {get;set;}
  //some other properties
}

我有一组针对每条记录运行的规则。每个规则都有一个类型和条件。

Rule
{
  RuleType Type {get;set;},
  Func<Record,bool> Condition {get;set;}
}

对于给定的规则类型,我想迭代记录列表并找到第一次满足规则条件。我想为所有规则类型执行此操作。

如果我在SQL中写这个,我可能会写一些东西

SELECT Type, MIN(Year) 
FROM Records, Rules
WHERE Rules.Condition(Records) = TRUE
GROUP BY Type

在LINQ中,我正在努力正确地将笛卡尔连接+单个条件+第一次出现+分组放在一起。

请协助。

感谢。

3 个答案:

答案 0 :(得分:2)

/* Calculate MIN(Year) */
var rule = rules.First(r => r.Type == specificType);
var result = records
    .Where(r => rule.Condition(r))
    .Min(r => r.Year)

/* or just some other rule */

var result = records.FirstOrDefault(r => rule.Condition(r));

答案 1 :(得分:0)

您可以使用双from这样的linq查询语法执行笛卡尔积:

var query= from r in Records
           from rule in Rules
           where rule.Condition(r)
           group new {rule.Type, r.Year } by rule.Type into g
           select g.OrderBy(e=>e.Year).FirstOrDefault();

答案 2 :(得分:0)

所以你有两个序列。一系列记录和一系列规则:

IEnumerable<Record> records = ...
IEnumerable<Rule> rules = ...

您对目标的文字描述与您的sql语句建议略有不同:

  

对于给定的规则类型,我想迭代记录列表并找到第一次满足规则条件。我想为所有规则类型执行此操作。

换句话说:对于每条规则,您只需要与规则匹配的第一条记录。

您的SQL语句建议您希望每个规则符合规则的所有记录按记录年度排序

您的文字要求。为此您的LINQ就像:

IEnumerable<Record> result = Rules.Select(rule =>
    records.Where(record => rule.Condition(record))
    .FirstOrDefault();

在单词中:从规则序列中的每个规则中,获取rule.Condition(记录)为真的记录序列中的第一个(或默认)记录。

这完全根据您的目标的文字描述,但是,从您知道的每条记录的结果记录序列中,记录符合规则。你不知道记录是第一个符合条件的规则。

如果您还想知道第一条记录与哪条规则匹配,请记住结果中的规则:

var result = rules.Select(rule => new
    {
        Rule = rule,
        FirstMatchingRecord = records
        .Where(record =>rule.Condition(record))
         .FirstOrDefault(),
     });

从规则集合中的每个规则中选择规则和匹配规则的记录集合的第一条记录,并将它们放在具有属性Rule和FirstMachingRecord的匿名对象中

请注意,每个第一个匹配记录都是您的记录集合的顺序。您的SQL语句表明您希望在升序年份对记录进行排序:

IEnumerable<Record> result = Rules.Select(rule =>
    records.Where(record => rule.Condition(record))
    .OrderBy(record => record.Year)
    .FirstOrDefault();

根据记录数量和匹配记录的数量,首先订购记录然后在where语句中使用有序结果可能是明智的:

var orderedRecords = records.Orderby(record => record.Year);
IEnumerable<Record> result = Rules.Select(rule =>
    orderedRecords.Where(record=> rule.Condition(record))
    .FirstOrDefault();

您的SQL语句表明您希望为每个规则配置一组规则,以按年份排序记录序列。在linq:

var result = rules.Select(rule => new
    {
        Rule = rule,
        MatchingRecords = records
            .Where(record => rule.Condition(record))
            .OrderBy(record => record.Year),
    });

对于规则集合中的每个规则,创建一个新的匿名对象,该对象包含规则,以及与按年份按升序排序的规则匹配的记录序列。从这个结果