我正在尝试使用NHibernate中的Criteria API获得不同的结果。我知道这可以使用HQL,但我更喜欢使用Criteria API来实现这一点,因为我的应用程序的其余部分仅使用此方法编写。我found this forum post,但无法让它发挥作用。有没有办法使用条件API来获得不同的结果集?
编辑:在执行此操作时,我还想排除主键列,它也是一个标识,并获取剩余的不同记录。有没有办法做到这一点?实际上,不同的记录返回重复项,因为主键对于每一行都是唯一的,但所有其他字段都是相同的。
答案 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();