Как выполнить объединенный запрос для таблиц «один ко многим» со свойством коллекции? - PullRequest
1 голос
/ 02 февраля 2011

У меня есть две таблицы; t_users (user_id pk, user_name, password) и t_transactions (trans_id pk, user_id fk, item_name, количество). Как мы видим, t_users является родительской таблицей, а t_transactions - дочерней таблицей, поэтому я создал для них два класса:

public class User
    {       
        public int ID {get; set;}
        public string Name {get; set;}
        public string Password {get; set;}
        public IList<Transaction> Transactions {get; set;}
        public IList<Group> Groups {get; set;}
    }

public class Transaction
    {
        public Transaction()
        {
        }

        public int ID {get; set;}
        public int UserID {get; set;}
        public string ItemName {get; set;}
        public decimal Amount {get; set;}
        public User User {get; set;}
    }

и вот мои отображения:

Пользователь

<class name="User" table="t_users" lazy="false">
        <id name="ID" column="user_id" />
        <property name="Name" column="user_name"/>
        <property name="Password" column="password" />
        <bag name="Transactions" lazy="false" cascade="all">
            <key column="user_id" />            
            <one-to-many class="Transaction" />
        </bag>      
        <bag name="Groups" table="t_users_groups" lazy="false" cascade="all" inverse="true">
            <key column="user_id" />
            <many-to-many column="group_id" class="Group" />
        </bag>      
    </class>

Сделка:

<class name="Transaction" table="t_transactions" lazy="false">
        <id name="ID" column="trans_id" />
        <property name="UserID" column="user_id"/>
        <property name="ItemName" column="item_name" />
        <property name="Amount" column="amount" />
        <many-to-one name="User" column="user_id" class="User" />
    </class>

Как бы я назвал этот запрос

SELECT u.user_id, u.user_name, u.password, t.trans_id, t.user_id, t.item_name, t.amount
      FROM t_users u INNER JOIN t_transactions t on u.user_id = t.user_id
      WHERE amount <= :limit

Какие должны возвращать уникальные родительские объекты (u), а дублированная дочерняя таблица (t) должна быть частью / помещена в свойство транзакции класса User?

Спасибо!

1 Ответ

1 голос
/ 02 февраля 2011

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

В hql:

from Transaction t 
where t.Amount <= :limit

Хотите ли вы получить свойство User?

from Transaction t
join fetch t.User
where t.Amount <= :limit

ТогдаВы можете создать именованный запрос или выполнить

session.CreateQuery(query).List<Transaction>();

Если вам нужна структура объекта, подобная вашему объекту домена, вы можете сделать следующее:

public class UserWithTransactionsViewModel
{
  public string UserName {get; set; }
  public IEnumerable<TransactionViewModel> Transactions {get; set;}
}

вы можете создать проекцию вПамять выглядит следующим образом:

var vms = session.CreateQuery(query)
       .List<Transaction>()
       .GroupBy(t => t.User)
       .Select( g => new UserWithTransactionViewModel
                        { 
                          UserName = g.Key.Name
                          Transactions = g.Select(t => new TransactionViewModel(....)).ToArray()
                        });

Другой подход будет заключаться в том, чтобы запрашивать пользователей с одной транзакцией с суммой, превышающей ..., а затем фильтровать транзакции в памяти при проецировании на модель представления или dto.Но мне это не нравится, потому что у вас есть логика для фильтрации в двух разных местах, это хуже по производительности, потому что вы получите в память даже транзакции, которые вам не нужны.

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

PS: вам не нужно свойство UserId в классе Transaction.Это ошибка дизайна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...