在多对多映射上使用查询来投影子查询

时间:2012-10-19 16:28:31

标签: nhibernate queryover

我有以下域名模型

public interface IAppliedTo
{
    public Guid Id { get; set; }
}

public class Widget
{
    public DateTime DateCreated { get; set; }
    public Guid Id { get; set; }
    public ISet<IAppliedTo> AppliesTo { get; set; }
}


public class Master : IAppliedTo
{
    public Guid Id { get; set; }
}

Widget映射将AppesTo定义为:

<set name="AppliesTo" table="WidgetAppliesTo" lazy="true" >
    <key column="WidgetId"></key>
    <many-to-any  id-type="Guid" meta-type="int" >
      <meta-value  class="Master" value="1"/>

      <column name="ObjectType" />
      <column name="ObjectId" />

    </many-to-any>
  </set>

我在Master上使用QueryOver编写查询,我想为适用于Master的任何Widget提取最后一个CreatedDate。

基本上我想要这样的东西:

            Master mast=null;
            Widget widg=null;
            var widgetQuery=QueryOver.Of<Widget>(()=>widg);

            var query = NHibernateSessionManager.Instance.GetSessionFrom()
                .QueryOver<Master>(() => mast)
                .Where(() => mast.Name == "Josh")
                .SelectList(l => 
                    l.SelectSubQuery(widgetQuery.Where(() => widg.AppliesTo.Contains(mast))
                        .Select(Projections.Max(() => widg.DateCreated))
                    )
                 );

如果我的AppliesTo是一个特定类型,我知道如何做到这一点,但我怎么能告诉nHibernate使用ObjectId。基本上我试图得到这个问题:

SELECT *,(SELECT MAX(DateCreated) 
          FROM Widget 
          INNER JOIN WidgetAppliesTo
            on Widget.Id=WidgetAppliesTo.ActivityId
            WHERE objectId=[master].Id)
FROM [Master]

2 个答案:

答案 0 :(得分:1)

这可能有效,但我无法测试

Master mast=null;

var query = NHibernateSessionManager.Instance.GetSessionFrom()
    .QueryOver(() => mast)
    .Where(() => mast.Name == "Josh")
    .SelectList(l =>
        l.SelectSubQuery(QueryOver.Of<Widget>()
            .JoinQueryOver(widg => widg.AppliesTo)
                .Where(obj => obj.Id == mast.Id)
            .Select(Projections.Max<Widget>(widg => widg.DateCreated))
        )
    );

答案 1 :(得分:0)

到目前为止,我设法做的最好的事情是使用Sql Projection来添加它。

    .Select(Projections.SqlProjection(
    "(select max(datecreated) from Widget wid
     inner join WidgetAppliesTo widTo on wid.Id=widTo.ActivityId and widTo.ObjectId=this_.Id)
 as lastTouchDate",
new string[]{"lastTouchDate"},
new NHibernate.Type.IType[]{NHibernateUtil.DateTime})
.WithAlias(() => jobDto.LastTouchDate));

虽然这有效但我很乐意看到一个非破解的解决方案