C'è un'implementazione del IQueryable<T>
nel quadro - MSDN: EnumerableQuery<T>
Se è possibile utilizzare questo sul client per costruire la query, è possibile ottenere l'intero albero di espressione dalla proprietà IQueryable<T>.Expression
.
Dovrai testarlo per vedere se funziona con quel Serializer di Expression Tree.
È quindi possibile serializzare l'espressione, spruzzarla attraverso il filo e quindi deserializzare.
allora il problema è che l'albero di espressione si basa su un EnumerableQuery<T>
.
Quindi è necessario per sostituire che con la vostra fonte IQueryable<T>
dal vero DbContext
Questo diventa un po ' disordinato, ma ho scritto un'implementazione utilizzando un 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;
}
e la ExpressionVisitor
stesso:
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);
}
}
Calli ng questo è semplice:
Type entityType = ...
Expression expression = ...
DbContext db = ...
ObjectContext ctx = ((IObjectContextAdapter) db).ObjectContext;
IQueryable query = FixupExpressionTree(ctx, entityType, expression);
So che questa non è una risposta alla tua domanda, ma per esperienza, non vorrei fare questo e invece scrivere servizi business dedicati. Si aggiunge complessità e si consente ai client di arrestare il sistema con query non valide. –