NHIbernate:投影所有属性的捷径?

时间:2011-04-23 07:34:17

标签: nhibernate icriteria queryover

我正在尝试按以下方式生成SQL:

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

使用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]

Title中有15个属性我想投射。是否有一种更简单的方法可以让我不必像上面开始那样单独投影每个属性?

7 个答案:

答案 0 :(得分:2)

我发现从NHibernate 3.2开始,如果不手动枚举所有属性,这是不可能的。

答案 1 :(得分:1)

如果你不介意ICriteria,这是有效的。我已经使用2.1.2进行了测试,但我不明白为什么如果不能使用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)
   ...;

答案 2 :(得分:1)

如果不手动枚举所有属性,则无法执行此操作。我通常使用CodeSmith生成投影代码。

答案 3 :(得分:0)

如果你想要Title对象,你可以写:

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

nHibernate将为您填充所有Title属性 有关详细信息,请参阅here

答案 4 :(得分:0)

是否可以使用您感兴趣的列在标题表上创建视图? 要么 也许你可能想尝试将Title类的属性分成两个类(TitleBase类和Title类,它继承自TitleBase类)。因此,您需要创建两个单独的映射文件。

假设您感兴趣的所有属性都在TitleBase类中,那么在上面提到的查询中使用它。

答案 5 :(得分:0)

我用这段代码解决了这个问题。我希望它能为你服务。我只是使用Bags,如果你需要使用ISet,只需更改比较。 PDM是实体,其属性我正在应用反射。您可以将此方法更改为通用。

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

答案 6 :(得分:0)

在NHibernate 5.1中通过Entity projections

可以实现
Title title = null;

var q = session
   .QueryOver(() => title)
   .Select(
      Projections.Entity(() => title),
      Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre")
)