我正在为我们公司正在进行的项目提供NHibernate,我想知道NHibernate是否可以优化,以便在使用Criteria查询语言时只检索表上的特定列.
例如.假设我有一个包含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
就是整数,我更喜欢拥有完整的Task对象,但所有字段都设置为默认值.这甚至可能吗?到目前为止,我看到的一切都说没有.
是的,您可以使用投影通过条件查询执行此操作.只需投影您希望使用的属性,只有那些将包含在已编译查询的select子句中.
http://nhibernate.info/doc/nh/en/index.html#querycriteria-projection
更新编辑
有几种方法可以实现这一点,但有一些限制.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转换器就会将这些投影映射到实际的类.此方法的限制是您映射的任何属性必须在POCO类中具有setter,这可以是受保护的setter,但它必须具有setter.
您也可以使用linq以稍微不同的方式执行此操作
var list = session.CreateCriteria(typeof (Task)) .SetProjection(Projections.ProjectionList() .Add(Projections.Property("Name")) .Add(Projections.Property("ID")) ) .List() .Select(l => new Task() {Name = (string) l[0], ID = (Guid) l[1]});
这只是使用linq将输出的索引列表映射到Task类的新实例.与上述相同的限制适用,除了这一点有点严重,因为映射的所有属性必须具有公共setter,因为这是linq用来填充对象的.
我希望这可以帮助你.
回应你的编辑:据我所知,这是不可能的.
但是,你可以做的是创建一个NHibernate已知的类,它只包含你感兴趣的属性.
例如,一个'TaskView'类,它只包含'Task'类的某些属性.
您必须在hbm.xml文件中"导入"TaskView类,以便NHibernate知道此类(请参阅导入映射).
然后,您可以使用Projection将"Task"转换为TaskView实例.当您查看NHibernate生成的查询时,您将看到它只会检索填充TaskView类所需的列.
像我在这里发布的东西: NHibernate和Collection Counts