Проецирование подзапроса с запросом на сопоставление "многие к любому"

У меня есть следующая модель домена

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

Отображение виджета имеет AppliesTo, определенный как:

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

Я пишу запрос с помощью QueryOver на Master, и я хочу извлечь последнюю CreatedDate для любого виджета, который применяется к Master.

По сути, я хочу что-то вроде:

            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 ответа

Решение

Пока лучшее, что мне удалось сделать, - это использовать 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));

Хотя это работает, я хотел бы увидеть не взломанное решение

Это может работать, но я не могу проверить это

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))
        )
    );
Другие вопросы по тегам