如何在LINQ查询中使用IEnumerable.Where()。Count()?

时间:2014-02-28 10:36:45

标签: asp.net-mvc linq entity-framework linq-to-entities

在Enitity Framework中我想在另一个linq查询的where子句中使用linq查询。

public class A {

}

public class B {
    public A A { get; set; }
}

public class AB {
    public A A { get; set; }
    public B B { get; set; }
}

IEnumerable<MassiveObject> filteredData = ...   // MassiveObject contains A and some more attributes

var query = from b in db.Bs
             .Include("A")
            where filteredData.Where(x => x.A.equals(b.A)).Count() > 0  // filteredAs contains an object that contains the same A as the b's A
            select new AB {
                A = filteredData.Where(a => a.equals(b.A)),
                B = b
            };

看起来LINQ不支持这一点。 “无法创建类型为'MassiveObject'的常量值。在此上下文中仅支持基本类型或枚举类型。”无论是第一次使用还是第二次使用嵌套的linq。

在执行查询后,如果没有循环查询结果,还有另一种方法吗?

4 个答案:

答案 0 :(得分:3)

Linq不支持在SQL构造中使用对象的枚举,因为没有办法让SQL stement开始。

拉出b,然后在该枚举中过滤。

答案 1 :(得分:3)

filteredData是一个存在于进程内存中的集合。另一方面,EF查询被转换为在SQL服务器上运行的SQL。

SQL服务器无法知道进程内存中存在哪些数据,即使它可以看到内存SQL仍然没有对象实例或迭代的概念。所以你要做的事情根本不可能。

答案 2 :(得分:1)

你不能像这样混合内存和SQL LINQ查询。相反,您需要在进行连接之前将SQL数据拉入内存。

尝试这样的事情:

var query =
    from b in db.Bs.Include("A").ToArray()
    join a in filteredData.Select(x => x.A) on b.A equals a into gas
    where gas.Any() // or use gas.Count() > 0
    select new AB
    {
        A = gas.First(),
        B = b,
    };

请注意将SQL数据带入内存的.ToArray()调用。

答案 3 :(得分:0)

目前还不是很清楚你想要实现的目标,但是,以前的查询可以通过各种方式在当前查询中使用,例如。

query2 = source.Where(s => query1.Contains(s));

或使用LINQ连接。

在你的情况下,它看起来像你试图重用过滤器,而不是查询。

您可以使用从IQueryable<T>IQueryable<T>的扩展方法或使用表达式来实现此目的。

e.g。

static class MyExtensions
{
    public static void IQueryable<T> FilterResults(this IQueryable<T> query)
    {
        return query.Where(i => i....);
    }
}

然后像这样使用:

query2 = query.FilterResults().Where(...);

有关使用表达式树的替代方法的详细信息,请参阅此MSDN article