是否可以使用linq(查询语法)中的范围变量作为参数?

时间:2017-10-17 19:26:32

标签: c# linq entity-framework-6

我正在尝试使用linq查询中的范围变量作为参数;

容易的事情;

private static Expression<Func<context.Table1, bool>> funstuff(context.Table2 data)
{
    return x => true;
}

使用它,就像另一个简单的例子,交叉连接;

var fun = from table2 in context.Table2
          from table1 in context.Table1.Where(funstuff(table2))
          select table1;

var f = fun.ToList();

我收到了这个错误;

  从范围''引用的'context.Table2'类型的变量'table2',   但它没有定义

是否可以使用范围变量作为实体框架6下的参数?

修改

context是实体框架的dbcontext

这个确切的代码确实有效;

var fun = from table2 in context.Table2
          from table1 in context.Table1.Where(x => table2.Id == 1)
          select table1;

var f = fun.ToList();

这不起作用;

private static Expression<Func<context.Table1, bool>> funstuff(context.Table2 data)
{
    return x => data.Id == 1;
}



var fun = from table2 in context.Table2
          from table1 in context.Table1.Where(funstuff(table2))
          select table1;

var f = fun.ToList();

我期待它会起作用。

2 个答案:

答案 0 :(得分:2)

我认为您的contextDbContext

虽然大多数功能都相似,但QueryableEnumerable之间存在差异。

IEnumerable对象包含枚举本地内存中集合中对象的所有代码。 IEnumerable obects可以在枚举时使用本地函数。

可查询枚举旨在在其他处理器上执行。 IQueryable对象包含一个表达式,该表达式可以转换为另一个处理器可以理解的格式。

此翻译不在Expression中,而在IQueryable的另一个属性中:ProviderProvider知道要在哪个类型的机器上执行Expression。根据请求,Provider会将此表达式翻译(编译)为本机理解的格式,并将翻译发送到此计算机。

对象context.Table2实现IQueryableIQueryable中的提供程序知道如何将查询转换为SQL。 SQL不知道您的任何个人函数,如funstuff,因此Provider不知道如何将其转换为SQL。事实上,DbSet甚至不支持所有类型的LINQ方法。

请参阅MSDN: Supported and Unsupported LINQ Methods (LINQ to Entities)

只要您的陈述是可以使用的,您就无法调用任何本地函数。

如果调用本地函数非常重要,可以将它们作为IEnumerable执行。您可以使用函数AsEnumerable执行此操作。这会将AsEnumerable输入的数据带到本地内存。之后,您可以调用所有本地函数,就像您的查询是IEnumerable

一样

然而,存在性能风险:如果输入是对象的最终结果,并且最终只会以一些对象结束,那么将所有这些信息带到本地内存是浪费。

结论:在调用AsEnumerable之前,尝试将传输到本地内存的数据限制为最终结果中所需的大小。之后,您可以调用任何您想要的本地功能。

答案 1 :(得分:1)

你不能这样做。考虑实体框架分析您的LINQ查询以将其转换为SQL查询。它一直分析到funstuff(table2)调用。它看到它是一个未知的方法调用表达式(所以不像SqlFunctions.GetDate())。好的,现在EF分析器需要调用此方法来获取表达式。如果方法没有参数或其参数是已知的 - 调用它没有问题。但是此方法参数表示查询参数table2。分析表达式时没有定义的值。在SQL查询执行期间,它只有一个值(范围)。那时,在SQL服务器上,当然不能使用该范围中的每个值调用您的方法。因此查询分析器绝对无法将您的查询转换为SQL并失败。