我可以在Where()中使用FirstOrDefault()或First()吗?

时间:2011-04-29 14:47:04

标签: c# linq nhibernate

我正在尝试实现此查询:

 data.Where(d => d.ObjectsA != null && 
   d.ObjectsA.First().ObjectsB != null && 
   d.ObjectsA.First().ObjectsB().First().Nr == 1)

在Nhibernate.Linq,但我有一个错误。 当我从Where()中删除First()所有工作。 我尝试了这个解决方案,但这并没有得到我需要的东西。

 data.Where(d => d.ObjectsA.Where(a.ObjectsB.Where(b=>b.Nr == 1).Any()).Any());

我可以在Where()中使用FirstOrDefault()或First()吗?

编辑:在我的数据库表中,此示例中的所有行都没有空值。

2 个答案:

答案 0 :(得分:3)

如果集合为空,

First()将抛出异常。在Where()调用中使用Any()确实可以解决问题,但您必须编写如下内容:

data.Where(d => d.ObjectsA != null && d.ObjectsA.Any()
    && d.ObjectsA.First().ObjectsB != null && d.ObjectsA.First().ObjectsB.Any()
    && d.ObjectsA.First().ObjectsB.First().Nr == 1);

这不是很好,因为First()最终会在同一数据上被多次调用。我建议在lambda表达式中添加一个body,并使用FirstOrDefault()的中间变量:

data.Where(d => {
    if (d.ObjectsA != null) {
        var firstA = d.ObjectsA.FirstOrDefault();
        if (firstA != null && firstA.ObjectsB != null) {
            var firstB = firstA.ObjectsB.FirstOrDefault();
            if (firstB != null) {
                return (firstB.Nr == 1);
            }
        }
    }
    return false;
});

编辑:上面的第二个代码片段显然不适用于LINQ to NHibernate。如果您可以使用查询语法而不必检查ObjectsAObjectsBnull,则可以写:

from d in data
let firstA = d.ObjectsA.FirstOrDefault()
let firstB = (firstA != null ? firstA.ObjectsB.FirstOrDefault() : null)
where (firstB != null && firstB.Nr == 1)
select d;

答案 1 :(得分:1)

如果条件中使用的集合可以为空,则可以使用默认变量和??使用FirstOrDefault()的nullif运算符。

var defaultA = new ObjectA();
var defaultB = new ObjectB();
var defaultBList = new List<ObjectB>();

data.Where(d => d.ObjectsA != null && 
   ((d.ObjectsA.FirstOrDefault() ?? defaultA).ObjectsB ?? defaultBList)
   .FirstOrDefault() ?? defaultB).Nr == 1)