是否可以在 LINQ 中编写一个漂亮的单行来获取第一个匹配的元素,或者是否与集合中的第一个元素不匹配?
E.g。你有一群鹦鹉,你想要黄鹦鹉,但如果没有黄鹦鹉 - 那么任何人都会这样做,就像这样:
Parrots.MatchedOrFirst(x => x.Yellow == true)
我试图避免双重访问SQL Server,我们在这种特殊情况下使用的ORM是Dapper。
答案 0 :(得分:3)
怎么样:
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();
答案 1 :(得分:2)
编辑:这是SQL解决方案的linq
首先建立一个方便的扩展
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);
答案 2 :(得分:0)
如果你想避免第二次SQL调用,并且因为需要分支逻辑,那么Dapper不太可能知道如何将LINQ查询转换为适当的SQL IIF,CASE或者你结束的任何其他SQL特定函数使用。
我建议您编写一个简单的存储过程来执行此操作并从Dapper中调用它。
根据其用途,如果此页面上只有一个或两个查询,并且与服务器位置相当接近(延迟明智),那么第二个简单的SELECT不会对整个应用程序造成太大影响。除非是在一个循环或其他东西,或者你的例子与关于第一个SELECT的成本的实际查询相比是微不足道的。