使用Criteria API从NHibernate获取不同的结果集?

时间:2008-11-25 17:15:45

标签: nhibernate

我正在尝试使用NHibernate中的Criteria API获得不同的结果。我知道这可以使用HQL,但我更喜欢使用Criteria API来实现这一点,因为我的应用程序的其余部分仅使用此方法编写。我found this forum post,但无法让它发挥作用。有没有办法使用条件API来获得不同的结果集?

编辑:在执行此操作时,我还想排除主键列,它也是一个标识,并获取剩余的不同记录。有没有办法做到这一点?实际上,不同的记录返回重复项,因为主键对于每一行都是唯一的,但所有其他字段都是相同的。

6 个答案:

答案 0 :(得分:88)

要执行不同的查询,您可以将标准上的投影设置为Projections.Distinct。然后,您可以包含要返回的列。然后通过将结果转换器设置为AliasToBeanResultTransformer,将结果转回强类型对象 - 传入应转换为结果的类型。在此示例中,我使用与实体本身相同的类型,但您可以专门为此查询创建另一个类。

ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.SetProjection(
    Projections.Distinct(Projections.ProjectionList()
        .Add(Projections.Alias(Projections.Property("FirstName"), "FirstName"))
        .Add(Projections.Alias(Projections.Property("LastName"), "LastName"))));

criteria.SetResultTransformer(
    new NHibernate.Transform.AliasToBeanResultTransformer(typeof(Person)));

IList<Person> people = criteria.List<Person>();

这会创建类似于(至少在SQL Server中)的SQL:

SELECT DISTINCT FirstName, LastName from Person

请注意,只会在结果中填充您在投影中指定的属性。

此方法的优点是过滤在数据库中执行,而不是将所有结果返回给您的应用程序,然后进行过滤 - 这是DistinctRootEntityTransformer的行为。

答案 1 :(得分:24)

此刻无法看到论坛帖子(断开链接?),所以也许这不是答案,但你可以添加一个DistinctRootEntityResultTransformer:

session.CreateCriteria(typeof(Product)
    .Add(...)
    .SetResultTransformer(new DistinctEntityRootTransformer())

答案 2 :(得分:6)

对于它的价值,NHibernate: Optimising Queries with Projections基本上帮助了我同样的问题。

答案 3 :(得分:1)

更简单,更好。如果您想使用DISTINCT获取整个实体,则可以使用Projections.Entity

{{1}}

“此”表示根实体。

答案 4 :(得分:-1)

我们正在使用最现代,最强大,最令人印象深刻的手段来处理这个......只有当你为这个真棒做好准备时,请继续阅读......并且它与标准没有关系......

CurrentSession()
    .QueryOver<GoodBadAndUgly>
    .Where(...)
    .TransformUsing(Transformers.DistinctRootEntity)

所以,如果你来这里希望有一种方法可以避免搞乱Criteria,即使你完全不得不朝着那个方向前进,只是为了在你的SQL中添加'DISTINCT'...不再搜索

答案 5 :(得分:-4)

我还遇到了不同数量的项目问题(我在映射文件中使用了fetch =“join”)。我使用Linq To Nhibernate来解决问题,该问题以下列方式使用:

       var suppliers = (from supplier in session.Linq<Supplier>()
                        from product in supplier.Products
                        where product.Category.Name == produtCategoryName
                        select supplier).ToList().Distinct();