Динамический поиск с использованием LINQ и динамически создаваемых предикатов - PullRequest
1 голос
/ 20 февраля 2009

У меня есть некоторые динамически создаваемые предикаты, которые имеют следующую сигнатуру, передаваемую в качестве параметров в функцию:

Expression<Func<TblTableR, bool>> TableRPredicate,
Expression<Func<TblTableN, bool>> suspectNamesPredicate,
Expression<Func<TblTableS, bool>> TableSPredicate,
Expression<Func<TblTableI, bool>> suspectTableIPredicate,

Я пытаюсь сделать запрос, используя следующее:

var registries = (from r in db.TblTableR.Where(TableRPredicate)
join s in db.TblTableS.Where(TableSPredicate) 
        on r.TblTableRID equals s.TblTableSTableRID into ss
from suspects in ss.DefaultIfEmpty()
    join si in db.TblTableI.Where(suspectTableIPredicate) 
        on suspects.TblTableSIndexCardID equals si.TblTableIID into sisi
    from suspectTableI in sisi.DefaultIfEmpty()
    join sn in db.TblTableN.Where(suspectNamesPredicate) 
        on suspectTableI.TblTableIID equals sn.TblTableNIndexCardID into snsn
    from suspectNames in snsn.DefaultIfEmpty()
    select r.TblTableRID).Distinct();

Это приводит к добавлению любого сгенерированного предложения where в оператор JOIN, например:

left outer join tblTableI on tblTableITableRID = tblTableRID 
   AND (expression created by predicate)

На самом деле происходит то, что созданный окончательный SQL-код неверен. Создается следующий тип sql

 select * from table1 left outer join table2 on field1 = field2 
    AND field3 = 'CRITERIA'

Проблема заключается в предложении AND в конце, возвращающем слишком много строк. По сути, я хотел бы включить в оператор предложение where, а не вставлять в него дополнительное условие.

Примерно так:

select * from table1 left outer join table2 on field1 = field2 
    WHERE field3 = 'CRITERIA'

Я попытался добавить предложение Where следующим образом:

...
...
...
select r.TblTableRID).Where(TableRPredicate).Distinct();

но это не скомпилируется из-за общих параметров для каждого предиката.

Если я изменю свой запрос LINQ, чтобы выбрать только одну таблицу и использовать предикат, предложение WHERE будет сгенерировано правильно.

Есть идеи?

1 Ответ

1 голос
/ 20 февраля 2009

(отредактировано после уточнения)

Шаг 1; изменить окончательный выбор, чтобы выбрать все три объекта в анонимный тип; для меня (тестирование на Northwind), то есть:

select new {emp, cust, order};

Шаг 2; примените свои фильтры к этому, используя метод расширения, который я добавил ниже; для меня эта фильтрация выглядит так:

var qry2 = qry.Where(x => x.emp, employeeFilter)
            .Where(x => x.cust, custFilter)
            .Where(x => x.order, orderFilter);

Шаг 3; Теперь выберите сущность / сущности, которые вы действительно хотите из этого фильтрованного запроса:

var data = qry2.Select(x => x.order)

А вот метод расширения:

static IQueryable<T> Where<T,TValue>(
    this IQueryable<T> source,
    Expression<Func<T, TValue>> selector,
    Expression<Func<TValue, bool>> predicate)
{
    var row = Expression.Parameter(typeof (T), "row");
    var member = Expression.Invoke(selector, row);
    var lambda = Expression.Lambda<Func<T, bool>>(
        Expression.Invoke(predicate, member), row);
    return source.Where(lambda);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...