2014-01-24 2 views
1

Это мой сценарий: мне нужно извлечь данные из сущности, используя запрос «ИЛИ» для свойства в связанном объекте.Выполнить выражение linq tree в

Это мои объекты:

public class Dealer 
{ 
    public virtual int id{get;set;} 
    public virtual string name{get;set;} 
    public virtual IList<Car> Cars{get;set;} 
} 

public class Car 
{ 
    public virtual int id{get;set;} 
    public virtual string name{get;set;} 
    public virtual int kw{get;set;} 
} 

Пример: Я хочу, чтобы извлечь все дилеры, которые имеют автомобили с 98кВт или 100кВт. Sql Пример:

SELECT Dealers.* FROM Dealers INNER JOIN Cars ON Cars.IdDealer = Dealers.Id WHERE Cars.kw = 98 OR Cars.kw = 100 

Я пытался использовать деревья выражений, но я не знаю, как их использовать. Я попытался это:

var dealers = Session.Linq<Dealers>(); 
ParameterExpression pe = Expression.Parameter(typeof(int), "kw"); 
Expression tot = null; 
var powers = new int[2]{98, 100}; 

for (var i = 0; i < powers.Length; i++) 
{ 
    Expression right = Expression.Constant(int.Parse(powers[i])); 
    if (i > 0) 
     tot = Expression.Or(tot, Expression.Equal(pe, right)); 
    else 
     tot = Expression.Equal(pe, right); 
} 
dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, null))); 

но я получаю эти ошибки компилятора на последней строке, где я пытаюсь выполнить выражение:

  • Невозможно преобразовать лямбда-выражения к типу string, потому что это не тип делегата
  • System.Collections.Generic.IList<Cars> не содержит определения для Any и лучший метод расширения перегрузки System.Linq.Enumerable.Any (System.Collections.Generic.IEnumerable, System.Func) имеет некоторые недопустимые аргументы
  • Аргумент 2: не может конвертировать из System.Linq.Expressions.Expression<System.Func<Cars,bool>> в System.Func<Cars,bool>

Любые предложения?

+0

Что такое «ошибка компилятора»? –

+0

Могу ли я сделать небольшое предложение, которое может приветствовать или не приветствовать. на мой взгляд, вам следует избегать использования RAW-выражений таким образом в открытой среде. я бы сердечно предложил, чтобы вы приняли более закрытый подход и посмотрели на нечто вроде предикат-строителя альбахари: http://www.albahari.com/nutshell/predicatebuilder.aspx сэкономит вам массу разочарований. некоторые большие рабочие примеры на странице тоже –

+0

@KonradMorawski добавил список ошибок – Albirex

ответ

0

В ролях результат Expression.Lambda к

Expression<Func<Car, bool>> 

и вам нужно передать в выражении параметра:

x.Cars.Any((Expression<Func<Car, bool>>)Expression.Lambda<Func<Cars, bool>>(tot, pe)) 
2

согласно комментарию, что я оставил:

. .. могу ли я сделать небольшое предложение, которое может приветствовать или не приветствовать. на мой взгляд, вам следует избегать использования RAW-выражений таким образом в открытой среде. я бы сердечно предложил, чтобы вы приняли более закрытый подход и посмотрели на нечто вроде предиката-строителя альбахари: albahari.com/nutshell/predicatebuilder.aspx сэкономит вам массу разочарований. некоторые замечательные рабочие примеры на странице тоже

Я не могу подчеркнуть достаточно преимуществ, которые это дало многим проектам, которые мы предприняли. Использование этой библиотеки/подход приводит к выражениям вдоль линий:

IQueryable<Product> SearchProducts (params string[] keywords) 
{ 
    var predicate = PredicateBuilder.False<Product>(); 

    foreach (string keyword in keywords) 
    { 
    string temp = keyword; 
    predicate = predicate.Or (p => p.Description.Contains (temp)); 
    } 
    return dataContext.Products.Where (predicate); 
} 

и т.д. Таким образом, вы можете строить довольно сложные операторы будут все внутренние спрятан. Это имеет смысл, особенно если у вас может быть больше младших разработчиков, работающих над кодом сейчас или в будущем. Я настоятельно призываю вас побаловать свою любознательность и побродить по ссылке и почувствовать себя лучше.

1

попробуйте изменить свой код, как этот

var dealers = Session.Linq<Dealers>(); 
ParameterExpression pe = Expression.Parameter(typeof(Car), "c"); 
var kw = Expression.Property(pe, "kw"); 
var powers = new string[2]{"98", "100"}; 

Expression tot = powers.Select(p=>Expression.Constant(int.Parse(p))) 
         .Select(p=>Expression.Equal(kw,p)) 
         .Aggregate((a,b)=>Expresion.Or(a,b)); 

также вам необходимо изменить Cars декларацию IEnumerable<Car> или IQueriable<Car>

Если IEnumerable<Car> затем вызвать его как

dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, pe).Compile())); 

If IQueriable<Car>, то назовите его

dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, pe))); 
Смежные вопросы