Подтвердить что ты не робот

Объекты С# PredicateBuilder: параметр 'f' не был связан в указанном выражении запроса LINQ to Entities

Мне нужно было создать динамический фильтр, и я хотел продолжать использовать сущности. По этой причине я хотел использовать PredicateBuilder из albahari.

Я создал следующий код:

var invoerDatums = PredicateBuilder.True<OnderzoeksVragen>();
var inner = PredicateBuilder.False<OnderzoeksVragen>();

foreach (var filter in set.RapportInvoerFilter.ToList())
{
    if(filter.IsDate)
    {
        var date = DateTime.Parse(filter.Waarde);
        invoerDatums = invoerDatums.Or(o => o.Van >= date && o.Tot <= date);
    }
    else
    {
        string temp = filter.Waarde;
        inner = inner.Or(o => o.OnderzoekType == temp);
    }
}

invoerDatums = invoerDatums.And(inner);
var onderzoeksVragen = entities.OnderzoeksVragen
                               .AsExpandable()
                               .Where(invoerDatums)
                               .ToList();

Когда я запускал код, был только 1 фильтр, который не был фильтром даты. Так что только внутренний предикат был заполнен. Когда предикат был выполнен, я получил следующую ошибку.

Параметр 'f' не был связан в заданный запрос LINQ to Entities выражение.

При поиске ответа я нашел следующую страницу. Но это уже реализовано в LINQKit.

Кто-нибудь еще испытал эту ошибку и знает, как ее решить?

4b9b3361

Ответ 1

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

например. (A OR B) AND (X OR Y), где один строитель создает A OR B, создается X OR Y и третий ANDs вместе.

Только с одним уровнем предикатов AsExpandable работал нормально, когда было введено более одного уровня, я получил ту же ошибку.

Мне не удалось найти какую-либо помощь, но через пробную версию и ошибку я смог заставить все работать. Каждый раз, когда я вызывал предикат, я следил за ним с помощью метода расширения Expand.

Вот немного кода, вырезанного для простоты:

public static IQueryable<Submission> AddOptionFilter(
    this IQueryable<Submission> query, 
    IEnumerable<IGrouping<int, int>> options)
{
    var predicate = options.Aggregate(
        PredicateBuilder.False<Submission>(),
        (accumulator, optionIds) => accumulator.Or(ConstructOptionMatchPredicate(optionIds).Expand()));
        query = query.Where(predicate.Expand());            
    return query;
}

Query - это IQueryable, у которого уже был вызов AsExpandable, ConstructOptionNotMatchPredicate возвращает выражение.

Как только мы закончили ошибку, мы, безусловно, смогли создать сложные фильтры во время выполнения против структуры сущности.

Edit:

Поскольку люди по-прежнему комментируют голосование и обсуждают это, я предполагаю, что он по-прежнему полезен, поэтому я использую другое исправление. В основном я прекратил использовать LinqKit и его предиктор-строитель в пользу этого Universal Predicate Builder, который имеет тот же API, но не нуждается в разворачивании вызовов, хорошо стоит проверить.

Ответ 2

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

// This predicate is the 1st predicate builder
var predicate = PredicateBuilder.True<Widget>();

// and I am adding more predicates to it (all no problem here)
predicate = predicate.And(c => c.ColumnA == 1);
predicate = predicate.And(c => c.ColumnB > 32);
predicate = predicate.And(c => c.ColumnC == 73);

// Now I want to add another "AND" predicate which actually comprises 
// of a whole list of sub-"OR" predicates
if(keywords.Length > 0)
{
    // NOTICE: Here I am starting off a brand new 2nd predicate builder....
    // (I'm not "AND"ing it to the existing one (yet))
    var subpredicate = PredicateBuilder.False<Widget>();

    foreach(string s in keywords)
    {
        string t = s;  // s is part of enumerable so need to make a copy of it
        subpredicate = subpredicate.Or(c => c.Name.Contains(t));
    }

    // This is the "gotcha" bit... ANDing the independent
    // sub-predicate to the 1st one....

    // If done like this, you will FAIL!
//  predicate = predicate.And(subpredicate); // FAIL at runtime!

    // To correct it, you must do this...
    predicate = predicate.And(subpredicate.Expand());  // OK at runtime!
}

Надеюсь, это поможет!: -)