Попытка создать QueryOver для многих со многими связями с проекциями

У меня есть две таблицы (Orders, транзакции) и таблица поиска TransactionsOrders, которая просто сохраняет столбцы OrderId и TransactionsId.

Для заказа может быть несколько транзакций, если транзакция не удалась (n) раз. И у объекта Order нет сведений о транзакциях.

Я считаю, что мне нужно будет использовать проекции, поскольку мне нужно будет возвращать все свойства заказа, а также два свойства из таблицы транзакций (Amount и TransactionDate), если для этого заказа существует успешная запись транзакции. Ниже приведен SQL, который будет генерировать правильный вывод.

   SELECT o.*, ct.TransactionDate, ct.Amount from Orders o
   LEFT OUTER JOIN 
     (SELECT * FROM CreditTransactionsOrders cto
          INNER JOIN CreditTransactions ct 
      ON ct.Id = cto.CreditTransactionId
      WHERE ct.Successful = 1) as ct 
   ON o.Id = ct.OrderId

Я попытался создать этот QueryOver и спроецировать нужные мне свойства из объекта Order и объекта Transaction, но не могу правильно преобразовать этот запрос SQL.

Конечным результатом является то, что мне нужно вернуть ВСЕ заказы, и мне нужно вернуть сумму и дату из объекта транзакции, если для этого заказа существует успешный. Я не совсем уверен, должен ли я использовать псевдонимы, но до сих пор все мои попытки были безуспешными.

1 ответ

Решение

Сначала вам нужно переписать ваш SQL в более дружественное состояние NHibernate:

SELECT o.*, ct.TransactionDate, ct.Amount from Orders o
  LEFT OUTER JOIN CreditTransactionsOrders cto 
    ON o.Id = cto.OrderId
  LEFT OUTER JOIN CreditTransactions ct 
    ON ct.Id = cto.CreditTransactionId AND ct.Successful = 1

Этот SQL будет давать те же результаты, что и ваш исходный запрос.

В NHibernate дополнительные критерии для объединения могут быть переведены как with заявление.

Таким образом, вы можете использовать перегрузку, принимающую withClause аргумент. Итак, при условии, что у вас есть Заказы и Кредитные транзакции, сопоставленные как многие ко многим. Вы должны получить следующий QueryOver.

Order o = null;
CreditTransaction ct = null;

var orders = session.QueryOver(() => o)
    .Left.JoinAlias(x => x.Transactions, () => ct, () => ct.Successful == 1)
    .List<Order>();

ОБНОВИТЬ

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

Order o = null;
CreditTransaction ct = null;

var orders = session.QueryOver(() => ct)
    .Right.JoinAlias(x => x.Orders, () => o, () => ct.Successful == 1)
    .Select(
        x => x.TransactionDate,
        x => x.Amount,
        x => o.Id // other Order fields
    ).TransformUsing(Transformers.AliasToBean<TransactionsDto>())
    .List<TransactionsDto>();

TransactionsDto класс должен содержать все выбранные поля.

Другие вопросы по тегам