简体   繁体   中英

NHibernate Custom IProjection that Runs a Sub-Query

Say I have 2 tables as follows:

MainTable (
    Id int,
    Name varchar(100)
)

RelatedTable (
    Id int,
    Value int,
    MainTableId int -- foreign key
)

There is a one-to-many relationship between MainTable and RelatedTable , such that RelatedTable.MainTableId references MainTable.Id .

I want to make a custom IProjection to be used as follows:

sess.CreateCriteria<MainTable>()
    .SetProjection(
        Projections.ProjectionList()
            .Add(Projections.Property("Id"))
            .Add(Projections.Property("Name"))
            .Add(new SumOfValuesProjection(/* arguments??? */))
    )
    .List();

That generates the following SQL:

select
    Id,
    Name,
    -- how to get this sub-query from IProjection?
    (select sum(Value)
    from RelatedTable
    where RelatedTable.MainTableId = MainTable.Id) as SumOfValues
from MainTable

This is just a small example of what I am trying to do. In my case, there could be dozens of these sub-query columns. They all use aggregate functions, but may not all use sum() .

I am looking to create a custom IProjection but am not quite sure where to start.

Any help would be greatly appreciated.

Maybe not the exact answer, but maybe more direct one. I would like to show, how to use current NHibernate features to execute similar SQL as needed.

The trick won't be in the custom IProjection , but in the call to already existing powerful IProjection implementation: Projections.SubQuery

var criteria = CreateCriteria<MainTable>("Main")
    .SetProjection(
        Projections.ProjectionList()
            .Add(Projections.Property("Id"))
            .Add(Projections.Property("Name"))

            // here we go, let's profit from existing IProjection
            .Add(Projections.SubQuery(
                   DetachedCriteria
                       .For<RelatedTable>("Related")
                       .SetProjection(Projections.Sum("Value"))
                       .Add(Restrictions.EqProperty("Main.Id", "Related.MainTableId")))
                   , "value")
                )
     ...
     ;

In case that this approach is not enough, I would suggest to observe how this functionality is implemented in current NHibernate code. Because still - NHibernate is Open Source ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM