Как стать автором
Обновить

Комментарии 21

А EntitySQL не пробовали?
Я просто к тому что построить такую строку, которая легко оттранслируется в соответствующий SQL дешевле и проще, чем извращаться с Expression tree
я плохо отношусь к строковым запросам в коде, это настоящий рассадник потенциальных ошибок!
Строго типизированное построение запросов сильно упростило мне жизнь, и мне захотелось решить проблему не отходя от LINQ
На мой взгляд, хреновый программист в виде прокладки между монитором и клавиатурой — вот он, настоящий рассадник потенциальных ошибок. А грамотно попользованное простое (ESQL) решение, напротив, читается и поддерживается гораздо легче, чем более-менее сложные игрища с ExprTree
А использование анонимного типа не помогает? По крайней мере, для Join используется именно он.
В Join анонимный тип нужен для того, чтобы указать поля для сравнения, а уже сам EF по этим полям генерирует SQL. Where такого не умеет, как минимум потому, что в Join подразумевается операция = а в Where может быть что угодно.
Если бы была возможность использовать сложные типы в Where, то нужно было бы для типов указывать equality comparer (что, кстати для анонимных типов невозможно), и EF пришлось бы как-то переводить толику из метода Equals в SQL, а это, мягко говоря, непростая задача!
Ну, компарер как раз не обязателен (потому что join работает без него). Более того, и с операциями все понятно (как для обычных ключей используется Contains, так и тут). Вопрос только в том, парсит ли это EF. Вечером проверю.
Не холивара ради… Но мне одному кажется, что здесь проблема не в инструментарии, а в неправильном проектировании базы и самого приложения, которое требует делать запросы, описанные в заглавии топика?
Это версионная система, в ней по определению нет Update и Delete. Единственное что можно делать, это вставлять новые записи с обновленной версией. Все запросы получают данные из БД только последней версии. И в этой системе, как и в любой другой, нужно получать список элементов по их идентификатору (составному в данном случае).

Например получение самих значений из БД по идентификаторам, которые вернул Sphinx…
А так разве не выйдет?
var ids = new[]{
    new {Id = 1, Revision= 2},
    new {Id = 1, Revision= 4},
    ...
};

var q = from i in context.Items
        where ids.Contains(new {i.Id, i.Revision})
        select i;
Я попробовал сейчас — выдает exception «Не удалось создать константу с типом „Анонимный тип“. В этом контексте поддерживаются только типы-примитивы и типы перечисления.»
Странно, у меня этот код сформировал корректный sql
SELECT [t0].[Id], [t0].[Revision]
FROM [Item] AS [t0]
WHERE (([t0].[Id] = @p0) AND ([t0].[Revision] = @p1)) OR (([t0].[Id] = @p2) AND ([t0].[Revision] = @p3))
Правда я на linq to sql проверял…
Может в этом дело…
Я проверял на EF4. Код прямо отсюда скопировал (только заменил Items) и он мне выдал ошибку…
Да, это как раз то, что я имел в виду. Жаль, что не работает.
PredicateBuilder пробовали?
Насколько я помню, помимо Or и And (которые, вероятно, будут не самым удобным вариантом) там можно описывать свои предикаты.
Да, я его не нашел когда искал решение, но у них не решена проблема с построением выражения. Они каждое новое подставляют справа, а это значит что при больших количествах этот компонент будет выдавать StackOverflowException, как я описал в топике.
ORM со всеми моделями, сущностями и коллекциями придумали для удобства использования. Если использование ORM становится неудобным, в нём пропадает всякий смысл, следует перейти к использованию SQL-запроса. Я понимаю что типизованные конструкции превращаются просто в строку, но сделать ошибку в нечитабельной ORM-конструкции на порядок больше чем в чётко выстроеном простом и читаемом запросе с несколькими AND или OR, на который глядишь и всё понятно.
Имхо, если запорожец не едет в гору, есть смысл доехать на велосипеде. Толкать в гору запорожец, только потому что он машина и едет быстрее немного нелогично. Так и тут, смысл использовать ORM в задаче, которую он не покрывает.
Так смысл этого поста как раз в том, что можно научить ORM делать еще и это!

Это как в запорожец поставить движок мощнее, чтобы он в гору смог въехать, и не пришлось возить с собой велосипед для таких случаев.
IMHO, у автора получилось вполне неплохое решение для приведённой задачи. Да и конструкция вполне читабельная.

На моих проектах такое не требуется, но если в будущем нужно будет делать такие операции (например в случае legacy database) — подумаю про его использование.

А не было ли (нет ли) возможности формировать запрос c условием IN на списке пар значений? Вот такого вида:
SELECT * FROM table_name WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) );

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории