Когда и каким образом запрос служб RIA добавляется в дерево выражений EF? - PullRequest
2 голосов
/ 18 апреля 2011

В моем домене RIA я выставляю

IQueryable <Клиент>

и на клиенте я могу запросить это как

DomainContext.Customers.Where (c => c.Id == theID)

У меня вопрос, как это выражение добавляется в запрос, отправляемый в базу данных, так как мой метод доменной службы не принимает IQueryable.

Существуют ли какие-либо «зацепки», предоставляемые RIA или EF для проверки / манипулирования выражением до того, как EF его проанализирует и sql будет отправлен в базу данных? Любые ссылки на то, как RIA работает под капотом, также приветствуются.

1 Ответ

2 голосов
/ 10 августа 2011

Я действительно наткнулся на ваш пост, потому что искал точно такую ​​же информацию.Я пишу простой поставщик запросов 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...