Я действительно наткнулся на ваш пост, потому что искал точно такую же информацию.Я пишу простой поставщик запросов MySql для использования со службами RIA.Поскольку ответа не было, я подумала, что добавлю свои выводы, хотя вопрос несколько устарел.Когда вы пишете свой метод запроса на стороне сервера, это может быть «IQueryable GetCustomers ()», но на стороне клиента у вас будет GetCustomersQuery ().На самом деле вы получаете данные не путем вызова метода GetCustomers, а путем вызова метода Load и передачи ему запроса.
Дело в том, что RIA затем будет использовать ваш метод GetCustomers для получения IQueryable,возьмите дерево выражений из составленного запроса на стороне клиента и скомпонуйте их вместе, и только тогда оно перечисляет IQueryable и возвращает результат.Вот почему поставщик запросов может видеть дерево выражений, которое вы создали на стороне клиента.Есть способ посмотреть на строку SQL-запроса, сгенерированную структурой сущностей, но я не уверен, как это сделать (попробуйте поискать метод ToTraceString).
Имея возможность взглянуть на дерево выражений, вы могли бысоздайте реализацию-заглушку интерфейсов IQueryable и IQueryProvider и используйте ее для просмотра дерева выражений (для отладки).Вот пример кода для реализации этих интерфейсов (с удаленными из IQueryProvider жизненно важными органами, заимствованными из The Wayward Weblog - Создание провайдера IQueryable ):
public class Query<T> : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable, IOrderedQueryable<T>, IOrderedQueryable
{
IQueryProvider provider;
Expression expression;
public Query(IQueryProvider provider)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
this.provider = provider;
this.expression = Expression.Constant(this);
}
public Query(IQueryProvider provider, Expression expression)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
if (expression == null)
{
throw new ArgumentNullException("expression");
}
if (!typeof(IQueryable<T>).IsAssignableFrom(expression.Type))
{
throw new ArgumentOutOfRangeException("expression");
}
this.provider = provider;
this.expression = expression;
}
Expression IQueryable.Expression
{
get { return this.expression; }
}
Type IQueryable.ElementType
{
get { return typeof(T); }
}
IQueryProvider IQueryable.Provider
{
get { return this.provider; }
}
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.provider.Execute(this.expression)).GetEnumerator();
}
}
public class QueryProvider : IQueryProvider
{
#region IQueryProvider Implementation
public IQueryable<T> CreateQuery<T>(Expression expression)
{
return new Query<T>(this, expression);
}
public IQueryable CreateQuery(Expression expression)
{
Type elementType = TypeSystem.GetElementType(expression.Type);
try
{
return (IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType), new object[] { this, expression });
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
public S Execute<S>(Expression expression)
{
return (S)this.Execute(expression);
}
public object Execute(Expression expression)
{
// You can write code here to look at the expression tree :P
return null;
}
#endregion
}