Получение заказов и количества заказов с помощью подзапросов

Я занимаюсь портированием старого приложения в Nhibernate.
Старое приложение широко использует пакеты ORACLE, и я хочу избавиться от этого.
Я начал сопоставлять несколько таблиц, и, похоже, все работает очень хорошо.
Теперь у меня есть запрос, которым я хотел бы управлять через QueryOver... или что-то подобное:

SELECT
    Orders.*
    (SELECT COUNT(*) FROM OrderLines
        WHERE OrderLines.CompanyCode = Orders.CompanyCode
              AND OrderLines.OrderNumber = Orders.OrderNumber
              AND NOT (OrderLines.OCLSCOM = 'Y' AND OrderLines.OCLSSEQ = 0)
              AND OrderLines.Status = 'R') OrderLinesCount
    FROM
        Orders
    WHERE
        AND Orders.CompanyCode = [CompanyCode];

[CompanyCode] – это фильтр.

Мне нужно сопоставить файлы (Orders и OrderLines), и моя ассоциация выглядит так:

<class name="Order" table="Orders">
    ...
    <set name="OrderLines" access="field.pascalcase-underscore" inverse="true" lazy="extra" cascade="none">
      <key>
        <column name="OrderNumber" not-null="true"/>
        <column name="CompanyCode" not-null="true"/>
      </key>
      <one-to-many class="OrderLine" not-found ="ignore"/>
    </set>
</class>

Первичный ключ для моей таблицы заказов — CompanyCode и OrderNumber.

Я хотел бы запросить заказы и получить количество строк для каждого заказа.

Я добился того, чего хотел, добавив свойство формулы (спасибо Ayende за это) в отображении заказа:

<property name="OrderLinesCount" formula="(SELECT COUNT(*) FROM OrderLines WHERE OrderLines.CompanyCode = CompanyCode AND OrderLines.OrderNumber = OrderNumber AND NOT (OrderLines.OCLSCOM = 'Y' AND OrderLines.OCLSSEQ = 0) AND OrderLines.Status = 'R')" />

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

Есть ли способ добиться того же результата с помощью подзапроса (QueryOver)?

Заранее спасибо за помощь.


person LeftyX    schedule 05.08.2011    source источник
comment
способ достижения того же результата с помощью подзапроса ›› вы имеете в виду подзапрос, отличный от SQL, или, другими словами, динамический запрос в коде?   -  person Abel    schedule 09.08.2011
comment
@Abel, я хотел бы избавиться от свойства формулы и использовать, если возможно, подзапрос (QueryOver).   -  person LeftyX    schedule 10.08.2011
comment
Имейте в виду, что формула выполняется для каждой строки и нет ленивой загрузки. Таким образом, производительность будет ужасной для больших наборов данных.   -  person Yavor Shahpasov    schedule 10.08.2011
comment
Почему возникает проблема перекомпилировать весь проект после изменения формулы? Чем изменение формулы отличается от изменения запроса QueryOver?   -  person Jakub Linhart    schedule 11.08.2011
comment
@Jakub Linhart: QueryOver дает вам возможность динамически строить выражения (критерии). Вещи, которые я делаю довольно часто, особенно в таких ситуациях.   -  person LeftyX    schedule 11.08.2011
comment
Итак, вы хотите изменить формулу во время выполнения?   -  person Jakub Linhart    schedule 13.08.2011
comment
@ Якуб Линхарт: Да, возможно. Требования моего клиента всегда таковы. Давайте поместим параметры конфигурации в файлы/базы данных, поэтому, если я захочу что-то изменить, мне не нужно вам звонить!.   -  person LeftyX    schedule 15.08.2011
comment
Затем вы можете поместить свои файлы сопоставления в базу данных:]   -  person Jakub Linhart    schedule 15.08.2011
comment
@Jakub Linhart: Да, это может быть идеей. Во всяком случае, я знаю, что могу сделать это с помощью подзапросов и QueryOver. Я почти нашел решение для этого. Я надеялся, что кто-то может помочь мне с этим. Как только я получу код, я помещу его здесь.   -  person LeftyX    schedule 15.08.2011


Ответы (2)


Возможно, это не совсем то, что вы ищете, но рассмотрели ли вы предложение where в коллекции. Вы можете вызвать order.OrderLinesFiltered.Count, чтобы получить значение

<set name="OrderLinesFiltered" table="OrderLines" 
access="field.pascalcase-underscore" inverse="true" lazy="extra"
cascade="none" 
where=" NOT (OCLSCOM = 'Y' AND OCLSSEQ = 0) AND Status = 'R' ">
  <key>
    <column name="OrderNumber" not-null="true"/>
    <column name="CompanyCode" not-null="true"/>
  </key>
  <one-to-many class="OrderLine" not-found ="ignore"/>
</set> 
person Yavor Shahpasov    schedule 10.08.2011
comment
Да, я знаю, что это будет выполняться для каждой строки, но я собираюсь отфильтровать набор данных, чтобы у меня никогда не было больше нескольких строк. У вас хорошая идея, но я ожидал чего-то другого, потому что, как я уже сказал, мой клиент однажды может попросить меня фильтровать по-другому. - person LeftyX; 11.08.2011

В конце концов я решил использовать свойство формулы:

<property name="OrderLinesCount" formula="(SELECT COUNT(*) FROM OrderLines WHERE OrderLines.CompanyCode = CompanyCode AND OrderLines.OrderNumber = OrderNumber AND NOT (OrderLines.OCLSCOM = 'Y' AND OrderLines.OCLSSEQ = 0) AND OrderLines.Status = 'R')" />

Однажды, если мне нужно будет изменить фильтр, я могу подумать об использовании фильтров nHibernate.

person LeftyX    schedule 23.02.2012