NHibernate - создать критерии на основе свойства, которое является списком - PullRequest
1 голос
/ 21 января 2010

У меня есть класс с именем LoanApplication, и у него есть настроенное свойство коллекции, называемое Workflow. В файле сопоставления я устанавливаю порядок извлечения записей рабочего процесса для сортировки по дате, поэтому текущий рабочий процесс всегда является первым элементом в списке.

Теперь я хочу выполнить запрос к текущему рабочему процессу, чтобы получить приложения LoanApplications, которые находятся на определенном шаге рабочего процесса с использованием API критериев. Я не совсем уверен, как это сделать. Вот как я отображаю коллекцию Workflow:

<bag name="ApplicationWorkflow" table="PreApplication.ApplicationWorkflow" generic="true" inverse="true" order-by="StartDate DESC"
  cascade="all" lazy="true">
  <key column="ApplicationID" />
  <one-to-many class="ApplicationWorkflow" />
</bag>

Вот как я получаю приложения (вот где мне нужно добавить фильтр по функциональности Current Workflow):

    public IList<Model.PreApplication.Application> GetCompletedApplications()
    {
        IList<Model.PreApplication.Application> result = null;

        using (ITransaction transaction = this.Session.BeginTransaction())
        {
            result = this.Session.CreateCriteria<Model.PreApplication.Application>()
                .AddOrder(new Order("EnteredDate", false))
                .List<Model.PreApplication.Application>();

            transaction.Commit();
        }

        return result;
    }

Спасибо за любую помощь!

Ответы [ 3 ]

2 голосов
/ 21 января 2010

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

желаемый SQL ...

select
    ...
from
    Application app
    inner join ApplicationWorkFlow currWorkFlow on app.id = currWorkFlow.application_id
where
    currWorkFlow.id = (
        select top 1 topFlow.id
        from ApplicationWorkFlow topFlow
        where topFlow.application_id = app.id
        order by topFlow.StartedDate desc
    )
    and currWorkFlow.step = @step

Критерии, чтобы вы туда попали ...

session.CreateCriteria<Application>("app")
    .CreateAlias("ApplicationWorkFlow", "currWorkFlow", NHibernate.SqlCommand.JoinType.InnerJoin)
    .Add(Subqueries.PropertyEq("currWorkFlow.id", 
        DetachedCriteria.For<ApplicationWorkFlow>("topFlow")
            .SetMaxResults(1)
            .SetProjection(Projections.Property("topFlow.id"))
            .AddOrder(Order.Desc("topFlow.StartDate"))
            .Add(Restrictions.EqProperty("app.id", "topFlow.Application.id"))))
    .Add(Restrictions.Eq("currWorkFlow.step", step))
    .List<Application>();
1 голос
/ 21 января 2010

Как насчет этого sql запроса?

SELECT * FROM Application app 
JOIN 
    (SELECT * FROM ApplicationWorkFlow aflo WHERE aflo.step = @step) AS aflo 
WHERE aflo.application_id = app.id

Упрощенный запрос с использованием критериев

var applications = 
     Session.CreateCriteria<Application>()
            .CreateAlias("ApplicationWorkFlow", "appflo", JoinType.LeftOuterJoin)
            .Add(Restrictions.Eq("appflo.Step", step)) 
            .List<Application>();

Соответствующий критерий запроса с использованием отдельных критериев

var detached = DetachedCriteria.For<ApplicationWorkFlow>()
                               .SetProjection(Projections.Id())
                               .Add(Restrictions.Eq("Step", step));

var applications = 
        Session.CreateCriteria<Application>()
               .CreateAlias("ApplicationWorkFlow", "appflo", JoinType.LeftOuterJoin)
               .Add(Subqueries.PropertyIn("appflo.Id", detachedCriteria))
                 .List<Application>();

Может кто-нибудь сказать мне, если два вышеуказанных запроса совпадают? Они генерируют тот же sql в моем случае. Если они одинаковы, почему следует использовать DetachedCriteria?

0 голосов
/ 21 января 2010

Предлагаю просто добавить ссылку на последний / активный Workflow. Критерии будут намного проще:)

public void AddLatestWorkflow(Workflow wf)
{
    this.Workflows.Add(wf);
    this.LatestWorkflow = wf;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...