LINQ to SQL:重用lambda表达式 [英] LINQ to SQL: Reuse lambda expression

查看:76
本文介绍了LINQ to SQL:重用lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我偶然发现了一些奇怪的LINQ to SQL行为-任何人都可以对此有所了解吗?

I stumbled over some strange LINQ to SQL behaviour - can anybody shed some light on this?

我想定义一个lambda表达式并在我的LINQ语句中使用它.以下代码可以正常工作:

I want to define a lambda expression and use it in my LINQ statement. The following code works fine:

[...]
Func<Table1, bool> lambda = x => x.Id > 1000;
var result = dataContext.Table1s.Where(lambda);
[...]

但是当我尝试在关联表的语句中使用我的lambda表达式时

But when I try to use my lambda expression in a statement on an associated table

[...]
Func<Table1, bool> lambda = x => x.Id > 1000;
var result = dataContext.Table2s.Where(x => x.Table1s.Any(lambda));
[...]

我得到一个例外:

Unsupported overload used for query operator 'Any'.

但是,我没有得到:当我将lambda直接放入查询中时,效果很好:

But, and this I don't get: It works fine when I put my lambda directly into the query:

[...]
var result = dataContext.Table2s.Where(x => x.Table1s.Any(y => y.Id > 1000));
[...]

为什么?!

谢谢.

推荐答案

好的,这是交易:dataContext.Table1sIQueryable<T>类型. IQueryable<T>定义采用谓词类型为Expression<Func<T, bool>>WhereAny方法. Expression<>包装器至关重要,因为这是LINQ to SQL将lambda表达式转换为SQL并在数据库服务器上执行的基础.

Okay, here's the deal: dataContext.Table1s is of type IQueryable<T>. IQueryable<T> defines Where and Any methods that take a predicate of type Expression<Func<T, bool>>. The Expression<> wrapper is critical, as this is what allows LINQ to SQL to translate your lambda expression to SQL and execute it on the database server.

但是,IQueryable<T>也包括IEnumerable<T>. IEnumerable<T>还定义了WhereAny方法,但是IEnumerable版本采用类型为Func<T, bool>的谓词.由于这是一个编译函数而不是表达式,因此无法将其转换为SQL.结果,此代码...

However, IQueryable<T> also includes IEnumerable<T>. IEnumerable<T> also defines Where and Any methods, but the IEnumerable version takes a predicate of type Func<T, bool>. Because this is a compiled function and not an expression, it can't be translated to SQL. As a result, this code...

Func<Table1, bool> lambda = x => x.Id > 1000;
var result = dataContext.Table1s.Where(lambda);

...将把每个记录从Table1s中拉出到内存中,然后过滤内存中的记录.可以,但是如果您的桌子很大,那真是个坏消息.

...will pull EVERY record out of Table1s into memory, and then filter the records in memory. It works, but it's really bad news if your table is large.

Func<Table1, bool> lambda = x => x.Id > 1000;
var result = dataContext.Table2s.Where(x => x.Table1s.Any(lambda));

此版本具有两个lambda表达式.第二个是直接传递到WhereExpression,其中包含对Func的引用.您不能将两者混为一谈,并且收到的错误消息告诉您对Any的调用期望使用Expression,但您传递的是Func.

This version has two lambda expressions. The second one, being passed directly into Where, is an Expression that includes a reference to a Func. You can't mix the two, and the error message you're getting is telling you that the call to Any is expecting an Expression but you're passing in a Func.

var result = dataContext.Table2s.Where(x => x.Table1s.Any(y => y.Id > 1000));

在此版本中,您的内部lambda会自动转换为Expression,因为这是您希望将代码通过LINQ to SQL转换为SQL的唯一选择.在其他情况下,您会强制将lambda设置为Func而不是Expression-在这种情况下,您不是这样,因此可以正常工作.

In this version, your inner lambda is automatically being converted to an Expression because that's the only choice if you want your code to be transformed into SQL by LINQ to SQL. In the other cases, you're forcing the lambda to be a Func instead of an Expression - in this case you're not, so it works.

有什么解决方案?实际上很简单:

What's the solution? It's actually pretty simple:

Expression<Func<Table1, bool>> lambda = x => x.Id > 1000;

这篇关于LINQ to SQL:重用lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆