【问题标题】:NHibernate - create criteria based on a property that is a listNHibernate - 基于作为列表的属性创建标准
【发布时间】:2010-01-20 21:04:58
【问题描述】:

我有一个名为 LoanApplication 的类,它设置了一个名为 Workflow 的集合属性。在映射文件中,我将工作流记录的检索顺序设置为按日期排序,因此当前工作流始终是列表中的第一项。

现在我想通过当前工作流进行查询,以使用 Criteria API 获取处于特定工作流步骤中的 LoanApplications。我真的不知道该怎么做。这是我映射工作流集合的方式:

<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>

这是我检索应用程序的方式(这是我需要通过当前工作流功能添加过滤器的地方):

    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;
    }

感谢您的帮助!

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    所以您需要列出当前工作流处于特定步骤的应用程序吗?您可以使用子查询仅加入当前工作流,然后限制到特定步骤。

    所需的 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>();
    

    【讨论】:

      【解决方案2】:

      这个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?

      【讨论】:

      • 谢谢!你的第一个简化查询要简单得多,并帮助我得到了我需要的东西。 +1
      【解决方案3】:

      我建议添加对最后/活动工作流的简单引用。标准会更简单:)

      public void AddLatestWorkflow(Workflow wf)
      {
          this.Workflows.Add(wf);
          this.LatestWorkflow = wf;
      }
      

      【讨论】:

      • 我不确定你在说什么。除了保留所有工作流的列表之外,还要添加另一个作为最新工作流的属性吗?如果这就是你所说的,你能告诉我如何获取最新工作流的属性吗?
      猜你喜欢
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-02
      • 2016-01-04
      • 2015-10-09
      • 1970-01-01
      相关资源
      最近更新 更多