Nhibernate 使用Critera查询时仅检索特定列?

Nhibernate 使用Critera查询时仅检索特定列?,nhibernate,Nhibernate,我正在为我们公司正在做的一个项目推荐NHibernate,我想知道在使用Criteria查询语言时,NHibernate是否可以优化为只检索表上的特定列 比如说。假设我有一个表,表上有30列,它使用NHibernate映射到一个对象,该对象与表是1对1的匹配。然而,对于系统的特定功能,我只关心其中两列 现在,我知道我可以使用HQL并执行CreateQuery,这将实现这一点,但这需要我为我想要有选择地检索的每个字段组合创建一个构造函数。从维护的角度来看,这可能是一个巨大的痛苦,因为在运行时之前我

我正在为我们公司正在做的一个项目推荐NHibernate,我想知道在使用Criteria查询语言时,NHibernate是否可以优化为只检索表上的特定列

比如说。假设我有一个表,表上有30列,它使用NHibernate映射到一个对象,该对象与表是1对1的匹配。然而,对于系统的特定功能,我只关心其中两列

现在,我知道我可以使用HQL并执行
CreateQuery
,这将实现这一点,但这需要我为我想要有选择地检索的每个字段组合创建一个构造函数。从维护的角度来看,这可能是一个巨大的痛苦,因为在运行时之前我不会捕获丢失的构造函数

我喜欢Criteria查询语言,因为它生成参数化SQL,而不是来自HQL的直接SQL查询。我看到有一个不包括某些列的“排除”模型,但在大多数情况下,我将包括比排除更多的列

多亏了下面的评论,我研究了预测,这对我来说仍然不是一个理想的情况。在使用以下各项时:

var list = session
    .CreateCriteria(typeof (Task))
    .SetProjection(Projections
                       .ProjectionList()
                       .Add(Projections.Property("Id")))
    .List();

最后,变量
list
仅为int,我更希望使用完整的任务对象,但所有字段都设置为默认值。这可能吗?到目前为止,我所看到的一切都是否定的。

是的,您可以通过使用投影的条件查询来实现这一点。只需投影您希望使用的属性,并且只有这些属性才会包含在已编译查询的select子句中

更新以进行编辑

有几种方法可以实现这一点,但也有一些局限性。1) NHibernate方式

var list = session.CreateCriteria(typeof (Task))
.SetProjection(Projections.ProjectionList()
                   .Add(Projections.Property("Name"), "Name")
                   .Add(Projections.Property("ID"), "ID")
)
.SetResultTransformer(Transformers.AliasToBean(typeof (Task)))
.List();
只需将属性名称作为别名指定给投影,AliasToBean transformer就会将这些投影映射到实际的类。此方法的限制是,映射的任何属性都必须在POCO类中具有setter,这可以是受保护的setter,但必须具有setter

您也可以使用linq以稍微不同的方式来实现这一点

var list = session.CreateCriteria(typeof (Task))
.SetProjection(Projections.ProjectionList()
                   .Add(Projections.Property("Name"))
                   .Add(Projections.Property("ID"))
)
.List<IList>()
.Select(l => new Task() {Name = (string) l[0], ID = (Guid) l[1]});
var list=session.CreateCriteria(任务类型))
.SetProjection(Projections.ProjectionList()项目)
.Add(Projections.Property(“名称”))
.Add(Projections.Property(“ID”))
)
.List()
.Select(l=>newtask(){Name=(string)l[0],ID=(Guid)l[1]});
这只是使用linq将输出的索引列表映射到任务类的新实例中。与上面相同的限制也适用,只是这有点严重,因为映射的所有属性都必须有一个公共setter,因为这是linq用来填充对象的


我希望这对您有所帮助。

我不确定这是否适合您的目的,但这只是一个建议:如果查询最终是您始终使用的东西,您可以为它创建一个SQL视图,然后根据该视图创建一个映射文件

NHibernate将像对待任何表一样对待视图,当然CRUD操作相对于数据完整性问题来说是个问题。

针对您的编辑: 据我所知,这是不可能的

但是,您可以做的是创建一个NHibernate已知的类,它只包含您感兴趣的属性

例如,“TaskView”类只包含“Task”类的某些属性。
您必须在hbm.xml文件中“导入”TaskView类,以便NHibernate了解该类(请参阅导入映射)。
然后,可以使用投影将“任务”转换为TaskView实例。当您查看NHibernate生成的查询时,您将看到它只检索填充TaskView类所需的列

类似于我在这里发布的内容:

您是否尝试过将默认构造函数设置为默认值?由于这是一个应用程序方面的问题,因此由您来解决。顺便问一下,为什么每个置换都需要一个构造函数?
Hibernate将使用全参数构造函数或无参数构造函数,然后使用setter,因此不需要做所有这些工作。事实上,如果我回忆正确,它可以做得更多。如果通过字节码操作魔法正确配置,它甚至可以设置所有私有字段,而不设置任何设置器。

我问了一个类似的问题,NHibernate似乎缺少自创建SQL以来应用程序使用的最常见功能。仅选择某些列的功能。这真是老生常谈,如果我参与了这个项目,我会拒绝任何逻辑,要求你跳出一个圈圈,上下颠倒,到处只是选择字段。即使有答案,我发现数小时的研究对于如此简单的事情来说太复杂了。我知道它可以在Nhibernate的linq提供程序中使用投影,但是对于非常复杂的查询,它是不可能的,所以只选择特定的字段。或者全部创建DTO/模型,或者必须开始创建不是原始DTO/模型的DTO/模型,在我看来,这些DTO/模型不必复制,因为用户只需要更少的记录。必须为基于sql的常规查询(而不是linq)提供排除/包含列表。我希望这些ORM能先做最基本的事情。如果数据库的结果集中没有返回字段,只需忽略填充模型。我希望有人能给出一个简单的解决方案/破解/解决方法。

请参阅我在回答您问题的帖子中的更新。如果有帮助,原始海报-Nhibernate Summer Screencast 2a展示了这一确切的方法IIRC。我认为这是一个非常优雅的解决方案,完全解决了我的问题。NH确实提供了这种机制,而且做得很好。这个问题最初是在NH3.0之前提出的,当时它变得更容易了。是的,有投影是很优雅的。但是不能选择部分列而不是完整的模型