有一个实现IQueryable<T>
在框架中——MSDN: EnumerableQuery<T> http://msdn.microsoft.com/en-us/library/cc190116.aspx
如果您可以在客户端上使用它来构建查询,您可以从IQueryable<T>.Expression
财产。
您必须对其进行测试,看看它是否适用于该表达式树序列化器。
var iQueryable = new EnumerableQuery<Model>( Enumerable.Empty<Model>() );
var query = iQueryable.Include( ... ).Where( ... ).OrderBy( ... );
var expressionTree = query.Expression;
然后,您可以序列化表达式,将其喷射到线路上,然后反序列化。
那么问题是表达式树是基于EnumerableQuery<T>
.
所以你需要用你的替换它IQueryable<T>
来源自您的真实DbContext
这得到一个bit凌乱,但我已经使用一个编写了一个实现ExpressionVisitor:
IQueryable FixupExpressionTree( ObjectContext ctx, Type entityType, Expression expression )
{
var tObjectContext = ctx.GetType();
var mCreateObjectSetOpen = tObjectContext.GetMethod( "CreateObjectSet", new Type[ 0 ] );
var mCreateObjectSetClosed = mCreateObjectSetOpen.MakeGenericMethod( entityType );
var objectQuery = ( ObjectQuery ) mCreateObjectSetClosed.Invoke( ctx, null );
var eFixed = new Visitor( objectQuery, entityType ).Visit( expression );
var qFixed = ( ( IQueryable ) objectQuery ).Provider.CreateQuery( eFixed );
return qFixed;
}
and the ExpressionVisitor
itself:
public class Visitor : ExpressionVisitor
{
ObjectQuery _Source = null;
Type _EntityType = null;
public Visitor( ObjectQuery source, Type entityType ) { _Source = source; _EntityType = entityType; }
protected override Expression VisitConstant( ConstantExpression node )
{
if ( !node.Type.Name.Contains( "EnumerableQuery" ) ) return base.VisitConstant( node );
var eConstantInstance = Expression.Constant( _Source );
var eConstantArgument = Expression.Constant( MergeOption.AppendOnly );
var tObjectQueryOpen = typeof( ObjectQuery<> );
var tObjectQueryClosed = tObjectQueryOpen.MakeGenericType( _EntityType );
var eMergeAsMethod = tObjectQueryClosed.GetMethod( "MergeAs", BindingFlags.Instance | BindingFlags.NonPublic );
return Expression.Call( eConstantInstance, eMergeAsMethod, eConstantArgument );
}
}
调用它很简单:
Type entityType = ...
Expression expression = ...
DbContext db = ...
ObjectContext ctx = ( ( IObjectContextAdapter ) db ).ObjectContext;
IQueryable query = FixupExpressionTree( ctx, entityType, expression );