Search code examples
c#nhibernateormprojectionqueryover

NHibernate QueryOver with SelectList


I have multiple queries against one table. As not all columns/properties are needed I specify the columns with the help of select list. Take the following method as example. This method is working

public IEnumerable<ResultDto> GetEntityAsDto(eStatusBinderProduktion fromState, eStatusBinderProduktion toState)
{
    EntityClass entityAlias = null;
    ResultDto resultAlias = null;

    var query = Session.QueryOver<EntityClass>(() => entityAlias)
      .Where(() => entityAlias.ProduktionStatus >= (byte)fromState)
      .And(() => entityAlias.ProduktionStatus <= (byte)toState);

    query.SelectList(list => list
         .Select(() => entityAlias.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
         .Select(() => entityAlias.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
         );

    return query.TransformUsing(Transformers.AliasToBean<ResultDto>())
          .List<ResultDto>();
}

As I need to define the SelectList in multiple methods, I tried to to move the SelectList into a separate method.

The following code is not working, NHibernate throws the exception

NHibernate.QueryException: 'could not resolve property: entity.PrimaryID of: MyProjectNamespace.DAL.Interfaces.Entities.EntityClass' "

public IEnumerable<ResultDto> GetEntityAsDto(eStatusBinderProduktion fromState, eStatusBinderProduktion toState)
{
    EntityClass entityAlias = null;
    ResultDto resultAlias = null;

    var query = Session.QueryOver<EntityClass>(() => entityAlias)
      .Where(() => entityAlias.ProduktionStatus >= (byte)fromState)
      .And(() => entityAlias.ProduktionStatus <= (byte)toState);

    MapPropertiesOfEntityToResult(entityAlias, resultAlias, query);

    return query.TransformUsing(Transformers.AliasToBean<ResultDto>())
          .List<ResultDto>();
}

private void MapPropertiesOfEntityToResult(EntityClass entity, ResultDto resultAlias, IQueryOver<EntityClass, EntityClass> query)
{
  query.SelectList(list => list
   .Select(() => entity.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
   .Select(() => entity.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
    );
}

Additional information:
- The mappings are correct
- table is filled with test data


Solution

  • We do not need alias for filling SelectList. We can profit from the Type parameters coming with IQueryOver<TRoot,TSubType>:

    //private void MapPropertiesOfEntityToResult(EntityClass entity
    //   , ResultDto resultAlias, IQueryOver<EntityClass, EntityClass> query)
    private void MapPropertiesOfEntityToResult( // no need for entity
          ResultDto resultAlias, IQueryOver<EntityClass, EntityClass> query)
    {
      query.SelectList(list => list
       //.Select(() => entity.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
       //.Select(() => entity.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
       .Select(entity => entity.PrimaryID).WithAlias(() => resultAlias.PrimaryID)
       .Select(entity => entity.SecondaryID).WithAlias(() => resultAlias.SecondaryID)
        );
    }
    

    The entity is now a parameter of the passed Function and its type is coming from IQueryOver definition