2013-07-16 6 views
3

Вот что я хочу сделать:вызова Expression в LINQ к Entities Выберите с LINQkit

class MyDbContext : DbContext 
{ 
    private static Expression<Func<MyClass, int>> myExpression1 = x => /* something complicated ... */; 
    private static Expression<Func<Item, int>> myExpression2 = x => /* something else complicated ... */; 

    public object GetAllData() 
    { 
     return (
      from o in MyClassDbSet.AsExpandable() 
      select new 
      { 
       data1 = myExpression1.Invoke(o),      // problem 1 
       data2 = o.Items.Select(myExpression2.Compile())  // problem 2 
      } 
     ); 
    } 
} 

UPDATE:

myExpression должен оставаться отрезанным от запроса, потому что я хочу, чтобы использовать его в нескольких запросах LINQ.

UPDATE 2:

Расстались myExpression в myExpression1 и myExpression2, чтобы сделать ясным тот факт, что я хочу использовать их по отдельности.

UPDATE 3:

Добавлено LINQkit примеру.

Проблема 1 броски: Невозможно привести объект типа «System.Linq.Expressions.FieldExpression» к типу «System.Linq.Expressions.LambdaExpression».

Задача 2 броски: ошибка поставщика Internal данных .NET Framework 1025.

+0

Посмотрите [LINQKit] (http://www.albahari.com/nutshell/linqkit.aspx). – svick

+0

Спасибо, я попробую! – billy

+0

@svick, я обновил вопрос, чтобы отразить проблемы, с которыми я сейчас пользуюсь LINQkit ... – billy

ответ

0

Вы можете попробовать использовать только один делегат не выражение:

private static Func<MyClass, int> myExpression = x => /* something complicated ... */; 

Проблема с этим подходом является то, что весь MyClass будет извлекаться из базы данных, а не только необходимые поля для вычисления выражения.

+0

Обновленный вопрос, чтобы показать, почему я не хочу этого ... – billy

5

При первой проблеме при использовании LinqKit вам нужно назначить свое выражение локальной переменной до .Invoke() ing. Более полное объяснение можно найти на this question.

Вторая проблема заключается в том, что выбрать метод принимает объект типа:

Expression<Func<TSource, TResult>> 

Это означает, что вы должны поставить лямбда-выражение принимать объект TSource в качестве параметра и возвращает объект TResult.

Ваш объект TSource - это элемент, то есть таблица, из которой вы делаете свой запрос. Ваш TResult - это int в вашем примере, это то, что вы определили в выражении.

Таким образом, вы должны вызвать .Invoke() для второго выражения, передающего объект Item в качестве параметра, так же, как вы передали объект MyClassDbSet «o». На самом деле, существует только синтаксическая разница в обоих операторах выбора, они существенно делают то же самое.

И вы не должны вызывать .Compile() на выражения, это производит:

Func<TSource, TResult> 

который является делегатом скомпилированной версии дерева выражения и не могут быть переведены в выражение SQL. Более подробную информацию можно найти here.

Он должен работать со следующими изменениями:

class MyDbContext : DbContext 
{ 
    private static Expression<Func<MyClass, int>> myExpression1 = x => /* something complicated ... */; 
    private static Expression<Func<Item, int>> myExpression2 = x => /* something else complicated ... */; 

    public object GetAllData() 
    { 
     Expression<Func<MyClass, int>> myLocalExpression1 = myExpression1; 
     Expression<Func<MyClass, int>> myLocalExpression2 = myExpression2; 

     return (
      from o in MyClassDbSet.AsExpandable() 
      select new 
      { 
       data1 = myLocalExpression1.Invoke(o), 
       data2 = o.Items.Select(item => myLocalExpression1.Invoke(item)) 
      } 
     ); 
    } 
} 
+0

Спасибо, я попробую локальные переменные .. , – billy