отложенное выполнение where в sql

у меня есть редактор, в котором люди могут создавать собственные sql-запросы. эти запросы являются объектами NHibernate.IQuery.

в нашем проекте мы используем NHibernate.Linq.LinqExtensionMethods.Query для получения объекта IQueryable, который можно использовать для применения фильтров, которые выполняются отложенно (все в БД).

теперь я хочу создать еще один фильтр, основанный на пользовательских sql-запросах. то, что я хочу, это что-то вроде этого:

queryable.Where(x=> <sql-query contains x>)

единственное, что я могу сделать прямо сейчас, это заранее выполнить sql-запрос, а затем отфильтровать запрос с помощью полученного списка элементов.

IList<T> elements = query.List<T>();
queryable.Where(x => elements.Contains(x)).ToList();

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

редактировать: первый запрос (тот, который дает список элементов для проверки во втором запросе) построен из простой sql-строки следующим образом:

ISQLQuery sqlQuery = CurrentSession.CreateSQLQuery(myQueryString);//create query
sqlQuery.AddEntity(typeof (T)); //set result type
IQuery query = sqlQuery.SetReadOnly(true);

person r3try    schedule 02.10.2014    source источник


Ответы (1)


Если у вас есть идентификаторы, вы должны выбрать их в своем query и сравнить с соответствующим столбцом идентификатора во втором запросе.

var elementIdsToUseInContain = query
    .Select(x => x.YourIdProperty);
var result = queryable
    .Where(x => elementIdsToUseInContain.Contains(x.YourIdPropertyToCompareTo))
    .ToList();

Примечание. Я не тестировал его, но это довольно стандартный Linq. Это зависит от того, поддерживает ли его NHibernate, чего я не знаю.

person Maarten    schedule 02.10.2014
comment
спасибо за ответ, но я думаю, что я не ясно выразил свою мысль. проблема не в фильтре в списке элементов... это довольно прямолинейно. но моя проблема в том, что я не хочу заранее выполнять список элементов. когда список становится очень длинным, мне нужно получить массу данных из базы данных, а затем снова отправить эти данные в базу данных во втором запросе. я хочу объединить два запроса, поэтому у меня есть только один запрос (чтобы минимизировать накладные расходы). - person r3try; 02.10.2014
comment
Я знаю. Мое решение делает это. Переменная elementIdsToUseInContain является запросом, а не результатом запроса. Если NHibernate достаточно умен, он объединит два запроса при построении своего SQL. Entity Framework и Linq-to-sql поддерживают это. Это приведет к одному оператору SQL (по крайней мере, с EF и L2S и, надеюсь, с NHibernate). - person Maarten; 02.10.2014
comment
ах, хорошо, не понял, что в первой части не было toList()... к сожалению, интерфейс NHibernate.IQuery не имеет метода contains, и поэтому я не могу понять, как объединить IQuery с IQueryable. Проблема в том, что мне нужно построить свой первый запрос из простого sql, поэтому я использую интерфейс IQuery. - person r3try; 02.10.2014