Переопределение IQueryProvider - PullRequest
2 голосов
/ 04 января 2011

Я пытаюсь подключить некоторую бизнес-логику к EntityFramework v4, и лучшее место, где я могу это сделать, - это непосредственно перед выполнением запроса.

Я надеялся, что смогу переопределить IQueryProvider по умолчанию, просто добавив хук метода в Execute (Expression expr):

    public TResult Execute<TResult>(Expression expression)
    {
        // Do stuff here.
        return this.BaseProvider.Execute<TResult>(expression);
    }

Однако мне трудно заставить IQueryable использовать мой IQueryProvider (у объекта ObjectQuery есть атрибут Provider {}, но он get; only; он возвращает предварительно определенный экземпляр класса). Есть ли способ использовать свой собственный IQueryProvider таким образом без записи всего нового стека запросов (ObjectSet, ObjectContext и т. Д.)?

EDIT

Извините: я не говорю о добавлении каких-либо новых классов, если это возможно, за исключением того, который реализует IQueryProvider. Обертка в принципе хороша, но поскольку я не собираюсь реализовывать IObjectSet или создавать подклассы ObjectQuery , оболочка будет использоваться только при первом проходе через CreateQuery:

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    {
        return this.BaseProvider.CreateQuery<TElement>(expression);
    }

После этого момента, когда я использую стандартный ObjectSet внутри оболочки, IQueryProvider вернется к предопределенному, и мой IQueryProvider не будет перехватывать дальнейшие вызовы.

Итак: есть ли способ реализовать и использовать IQueryProvider БЕЗ попытки добавить оболочку, что заставляет меня использовать полный пользовательский стек объектов IQueryxxx?

1 Ответ

1 голос
/ 04 января 2011

Да, просто подключитесь к запрашиваемому провайдеру в методах CreateQuery и Execute.

public object Execute(Expression expression)
{
 //do stuff here
 return _queryable.Provider.Execute(expression);
}

Вам просто нужно внедрить запрашиваемый объект, например:

public class MyQueryable<T> : IOrderedQueryable<T>
{
 public MyQueryable(IQueryable<T> toWrap)
  : this(equipment, Expression.Constant(equipment.AsQueryable()))
 {
 }

 public MyQueryable(IQueryable<T> toWrap, Expression expression)
 {
  Wrapped = toWrap;
  Provider = new MyProvider<T>(toWrap);
  Expression = expression;
 }

 public IEnumerator<TModel> GetEnumerator()
 {
  return Wrapped.GetEnumerator();
 }

 IEnumerator IEnumerable.GetEnumerator()
 {
  return GetEnumerator();
 }

 public Expression Expression { get; private set; }

 public Type ElementType
 {
  get { return typeof(T); }
 }

 public IQueryProvider Provider { get; private set; }
 internal IQueryable<T> Wrapped { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...