NHIbernate: Shortcut for projecting all properties?
Asked Answered
S

7

8

I'm trying to generate SQL along the lines of:

SELECT 
  t.*, 
  SELECT (...)
FROM Title t
[trimmed]

using QueryOver

Title title = null;

var q = session
   .QueryOver(() => title)
   .Select(
      Projections.Alias(Projections.Property<Title>(t => t.Id), "Id"),
      Projections.Alias(Projections.Property<Title>(t => t.Name), "Name"),
      ....
      Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre")
)
[code trimmed]

There are 15 properties in Title that I would like to project. Is there an easier way of doing it so that I don't have to project each property individually as I've started to do above?

Spray answered 23/4, 2011 at 7:34 Comment(3)
I take it you don't want to use HQL?Atalaya
I prefer ICriteria, but I'm open to using HQL. What did you have in mind?Spray
Additionally, if the code I've posted above is the only way to do it using ICritiera, I'd appreciate confirmation.Spray
S
2

I've discovered that as of NHibernate 3.2, this is not possible without manually enumerating all of the properties.

Spray answered 28/6, 2011 at 17:38 Comment(0)
W
3

If you don't mind ICriteria, this works. I have tested with 2.1.2, but I can't see why if wouldn't work with 3.x.

var projectionList = Projections.ProjectionList();
var metadata = session.SessionFactory.GetClassMetadata(typeof(Title));
foreach (var name in metadata.PropertyNames)
{
    projectionList.Add(Projections.Property(name), name);
}
var criteria = DetachedCriteria.For<Title>()
   .SetProjection(projectionList)
   ...;
Woodley answered 7/11, 2011 at 17:20 Comment(0)
S
2

I've discovered that as of NHibernate 3.2, this is not possible without manually enumerating all of the properties.

Spray answered 28/6, 2011 at 17:38 Comment(0)
T
1

It is not possible to do this without manually enumerating all of the properties. I usually use CodeSmith to generate projection codes.

Triable answered 10/3, 2012 at 2:5 Comment(0)
T
0

If you want Title objects, you can just write:

IList<Title> list = session.QueryOver<Title>.Where(/*some condition*/).List();  

nHibernate will populate all of the Title attributes for you.
see here for further detail.

Tactual answered 24/4, 2011 at 23:7 Comment(1)
thanks for your response. This isn't what I'm looking for, though. As you can see in the code I posted, I'm trying to select all of the values in the Title table in addition to a value that is generated by the subquery.Spray
H
0

Is it possible to create a view on the title table with the columns that you are interested in? or Perhaps you may want to try splitting the properties of Title class across two classes (TitleBase class and Title class which is inherited from TitleBase class). Accordingly you need to create two separate mapping files.

Suppose if all the properties that you are interested in are in TitleBase class, then use it in the above mentioned query.

Hunkers answered 25/4, 2011 at 9:36 Comment(0)
H
0

I have solved it with this code. I hope it can serve you. I just use Bags, just change comparison if you need to use ISet for example. PDM is Entity whose properties i am applying reflection over. You could change this method to be generic.

        ProjectionList list = Projections.ProjectionList();            
        var metadata = session.SessionFactory.GetClassMetadata(typeof(PDM));

        foreach (var name in metadata.PropertyNames)
        {
            PropertyInfo property = typeof(PDM).GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name));
            FieldInfo field = typeof(PDM).GetFields(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name));

            if (property != null)
            {
                if (!property.PropertyType.Name.Contains("IList"))
                {
                    list.Add(Projections.Property(name), name);
                }
            }

            if (field != null)
            {
                if (!field.FieldType.Name.Contains("IList"))
                {
                    list.Add(Projections.Property(name), name);
                }
            }
        }          
Henceforth answered 14/10, 2013 at 10:45 Comment(0)
D
0

It's possible in NHibernate 5.1 via Entity projections:

Title title = null;

var q = session
   .QueryOver(() => title)
   .Select(
      Projections.Entity(() => title),
      Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre")
)
Donavon answered 19/4, 2018 at 5:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.