Tim*_*vis 8 c# linq iqueryable expression-trees
我有一个Linq提供程序成功地从我选择的数据源获取数据,但是我现在想要做的是我有我的过滤结果集,允许Linq to Objects处理Expression树的其余部分(对于像Joins这样的东西,投影等)
我的想法是我可以通过ExpressionVisitor将结果集IEnumerable替换为包含我的IQueryProvider的表达式常量,然后返回该新表达式.还从我的IQueryable返回IEnumerable的提供程序......但这似乎不起作用:-(
有任何想法吗?
编辑:这里有一些好的答案,但给出了表格......
var qry = from c in MyProv.Table<Customer>()
Join o in MyProv.Table<Order>() on c.OrderID equals o.ID
select new
{
CustID = c.ID,
OrderID = o.ID
}
Run Code Online (Sandbox Code Playgroud)
在我的提供程序中,我可以轻松地从客户和订单中获取2个结果集,如果数据来自SQL源,我将构建并传递SQL Join语法,但是这种情况下数据不是来自SQL源,所以我需要做的代码中加入...但我说我有2分结果集,和LINQ到对象可以做一个连接...(以及后来的投影)这将是真正的好,只是代替表达常数MyProv.Table<Customer>和MyProv.Table<Order>用List<Customer>和List<Order>让一个List<>提供者处理表达式......这可能吗?怎么样?
以前的两个答案都有效,但如果你使用AsEnumerable()将IQueryable强制转换为IEnumerable,它会更好:
// Using Bob's code...
var result = datacontext.Table
.Where(x => x.Prop == val)
.OrderBy(x => x.Prop2)
.AsEnumerable() // <---- anything after this is done by LINQ to Objects
.Select(x => new { CoolProperty = x.Prop, OtherProperty = x.Prop2 });
Run Code Online (Sandbox Code Playgroud)
编辑:
// ... or MichaelGG's
var res = dc.Foos
.Where(x => x.Bla > 0) // uses IQueryable provider
.AsEnumerable()
.Where(y => y.Snag > 0); // IEnumerable, uses LINQ to Objects
Run Code Online (Sandbox Code Playgroud)
我所追求的是将表达式树中的 Queryable<> 常量替换为具体的 IEnumerable (或通过 .AsQueryable() 实现 IQueryable)结果集...这是一个复杂的主题,可能只对 Linq 有意义深陷表达式树访问者等的提供者作者。
我在 msdn 演练中发现了一个片段,它的作用类似于我所追求的,这给了我前进的方向......
using System;
using System.Linq;
using System.Linq.Expressions;
namespace LinqToTerraServerProvider
{
internal class ExpressionTreeModifier : ExpressionVisitor
{
private IQueryable<Place> queryablePlaces;
internal ExpressionTreeModifier(IQueryable<Place> places)
{
this.queryablePlaces = places;
}
internal Expression CopyAndModify(Expression expression)
{
return this.Visit(expression);
}
protected override Expression VisitConstant(ConstantExpression c)
{
// Replace the constant QueryableTerraServerData arg with the queryable Place collection.
if (c.Type == typeof(QueryableTerraServerData<Place>))
return Expression.Constant(this.queryablePlaces);
else
return c;
}
}
}
Run Code Online (Sandbox Code Playgroud)