Linq检查子查询是否为空而不命中远程数据库

时间:2012-03-23 18:58:26

标签: c# linq c#-4.0 linq-to-entities

我有一个linq子查询如下:

        for (int i = 0; i < parentAttributes.Length; i++)
        {
            Guid parent = parentAttributes[i];
            var subQuery = from sc in db.tSearchCluendexes
                           join a in db.tAttributes on sc.AttributeGUID equals a.GUID
                           join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID
                           where a.RelatedGUID == parent && userId == pc.CPSGUID                             
                           select sc.CPSGUID;

            query = query.Where(x => subQuery.Contains(x.Id));
        }

基本思想是我根据执行次数不确定的子查询的结果过滤数据列表(由查询变量表示)。

但是我现在有一个问题,即如果子查询实际包含数据并且我不想在循环的每次迭代中执行子查询(例如通过使用Count(我),我只想执行查询中的where。 )或ToList())因为这将击中远程资源。如果我们认为方法HasData()实际返回true或false,那么就像下面这样:

        for (int i = 0; i < parentAttributes.Length; i++)
        {
            Guid parent = parentAttributes[i];
            var subQuery = from sc in db.tSearchCluendexes
                           join a in db.tAttributes on sc.AttributeGUID equals a.GUID
                           join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID
                           where a.RelatedGUID == parent && userId == pc.CPSGUID                             
                           select sc.CPSGUID;

            if (subQuery.HasData())                
               query = query.Where(x => subQuery.Contains(x.Id));
        }

欢迎提出建议。

2 个答案:

答案 0 :(得分:4)

您使用CountToList的建议并不是查看查询是否有任何结果的最快方法。您应该使用Any方法:

if (subQuery.Any())
{            
   query = query.Where(x => subQuery.Contains(x.Id));
}

请注意,这仍将立即进行评估。如果你想延迟执行,你应该把它放在lambda函数中。

query = query.Where(x => !subQuery.Any() || subQuery.Contains(x.Id));

答案 1 :(得分:0)

在对Mark的响应进行一些非常详细的检查后,我可以确认Any()应该在lambda表达式中,否则代码将在循环的每次迭代期间直接调用数据库(不可取)。

因此,为了完整起见,如果您遇到类似的问题,我建议使用的代码:

        for (int i = 0; i < parentAttributes.Length; i++)
        {
            Guid parent = parentAttributes[i];
            var subQuery = from sc in db.tSearchCluendexes
                           join a in db.tAttributes on sc.AttributeGUID equals a.GUID
                           join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID
                           where a.RelatedGUID == parent && userId == pc.CPSGUID                             
                           select sc.CPSGUID;


            query = query.Where(x => !subQuery.Any() || subQuery.Contains(x.Id));                
        }

此代码将一系列存在的语句连接到sql,最终将在该过程的后期调用。如果lambda之外有Any(),那么这些SQL都是单独调用的。

再次感谢马克 - 顶级男士。