Попытка создать 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
класс должен содержать все выбранные поля.