在许多情况下,我想在服务器端进行一些过滤(有时是投影),然后切换到客户端来执行 LINQ 提供程序本身不支持的操作。
天真的方法(基本上就是我现在所做的)是将其分解为多个查询,类似于:
var fromServer = from t in context.Table
where t.Col1 = 123
where t.Col2 = "blah"
select t;
var clientSide = from t in fromServer.AsEnumerable()
where t.Col3.Split('/').Last() == "whatever"
select t.Col4;
然而,很多时候,这会带来比其真正价值更多的代码/麻烦。我真的很想在中间“切换到客户端”。我尝试了使用查询延续的各种方法,但是在第一个查询末尾执行“select t into foo”之后,foo仍然是一个单独的项目,而不是集合,所以我不能 AsEnumerable() 它。
我的目标是能够写出更像这样的东西:
var results = from t in context.Table
where t.Col1 = 123
where t.Col2 = "blah"
// Magic happens here to switch to the client side
where t.Col3.Split('/').Last() == "whatever"
select t.Col4;
好吧,首先你绝对不应该使用这里的代码。它是由训练有素的特技仓鼠编写的,这些仓鼠受过训练,在处理这种性质的代码时不会呕吐。
你应该绝对地选择您了解的选项之一:
- 使用“临时”变量(如果您可以将该变量静态键入为
IEnumerable<T>
那么你不需要打电话给AsEnumerable
- 当然,如果你有一个匿名类型作为元素类型,那么这将不起作用)
- 使用括号来调用
AsEnumerable
- 使用“流利”或“点符号”语法来使
AsEnumerable
打电话适应。
然而,你can使用查询表达式的翻译方式来施展一些魔法。您只需使查询表达式中具有表示形式的标准查询运算符之一具有不同的翻译即可。这里最简单的选项可能是“Where”。只需编写您自己的扩展方法即可IQueryable<T>
and a Func<T, SomeType>
where SomeType
isn't bool
,而你却离开了。这是一个例子,首先是黑客本身,然后是它的示例使用......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
public static class QueryHacks
{
public static readonly HackToken TransferToClient = HackToken.Instance;
public static IEnumerable<T> Where<T>(
this IQueryable<T> source,
Func<T, HackToken> ignored)
{
// Just like AsEnumerable... we're just changing the compile-time
// type, effectively.
return source;
}
// This class only really exists to make sure we don't *accidentally* use
// the hack above.
public class HackToken
{
internal static readonly HackToken Instance = new HackToken();
private HackToken() {}
}
}
public class Test
{
static void Main()
{
// Pretend this is really a db context or whatever
IQueryable<string> source = new string[0].AsQueryable();
var query = from x in source
where x.StartsWith("Foo") // Queryable.Where
where QueryHacks.TransferToClient
where x.GetHashCode() == 5 // Enumerable.Where
select x.Length;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)