如果没有匹配项,则获取第一个单个匹配元素或第一个?

Get First Single matched element or First if there's no match?

LINQ 中是否可以编写一个漂亮的单行代码来获取 第一个匹配的元素,或者如果没有匹配则获取第一个元素在集合中?

例如你有一组鹦鹉,你想要黄色鹦鹉,但如果没有黄色鹦鹉 - 那么任何一只都可以,像这样:

Parrots.MatchedOrFirst(x => x.Yellow == true)

我试图避免重复访问 SQL 服务器,我们在这种特殊情况下使用的 ORM 是 Dapper

怎么样:

var matchedOrFirst = Parrots.FirstOrDefault(x => x.Yellow == true) 
    ?? Parrots.FirstOrDefault();

编辑

对于结构,这应该有效:

var matchedOrFirst = Parrots.Any(x => x.Yellow == true) 
    ? Parrots.First(x => x.Yellow == true)
    : Parrots.FirstOrDefault();

如果您想避免第二次 SQL 调用并且因为需要分支逻辑,Dapper 不太可能知道如何将您提出的 LINQ 查询转换为适当的 SQL IIF,CASE ,或您最终使用的任何其他 SQL 特定功能。

我建议您编写一个简单的存储过程来执行此操作并从 Dapper 调用它。

不过,根据它的使用情况,如果此页面上已经只有一两个查询,并且位置合理地靠近服务器(延迟明智),则第二个简单的 SELECT 不会伤害总体应用不多。除非它处于循环中或其他情况,否则与有关第一个 SELECT.

的成本的实际查询相比,您的示例是微不足道的

编辑:这是一个 linq to SQL 解决方案

首先构建一个方便的扩展

public static T MatchedOrFirstOrDefault<T>(this IQueryable<T> collection, System.Linq.Expressions.Expression<Func<T, Boolean>> predicate)
{
  return (from item in collection.Where(predicate) select item)
                    .Concat((from item in collection select item).Take(1))
                    .ToList() // Convert to query result
                    .FirstOrDefault();
}

使用代码

var matchedOrFirst = Parrots.MatchedOrFirstOrDefault(x => x.Yellow);