我是否在使用Nhibernate Query Over fetch做错了什么?

时间:2011-06-02 23:04:55

标签: nhibernate fetch eager-loading queryover

我有这个

   using (ITransaction transaction = session.BeginTransaction())
        {
            Task tAlias = null;
            CompletedTask cAlias = null;

            List<Task> tasks = session.QueryOver<Task>(() => tAlias)
                .Where(Restrictions.In(Projections.Property(() => tAlias.Course.Id), courseIds))
                .Fetch(pt => pt.PersonalTaskReminders).Eager
                .List<Task>().ToList().ConvertToLocalTime(student);


            transaction.Commit();

            return tasks;
        }

    PersonalTaskReminders == Collection

因此任务可以有许多personalTask​​Reminders。我发现如果我设置2个personalTask​​Reminders(所以PersonalTask​​Reminders现在将从db中收集2行)

它返回相同的任务两次。

因此,如果我有50个personaltaskReminders用于该任务。我会得到50个相同任务的结果。我不明白为什么。

如果我删除了急切的加载。我按照预期从数据库中获取了一个任务。

2 个答案:

答案 0 :(得分:17)

很明显,因为预先获取会导致与2个表连接。要消除重复的结果,您应该使用DistinctRootEntityTransformer。

顺便说一句,NHibernate为IN子句提供了更好的语法。所以你的查询应该是这样的:

    var tasks = Session.QueryOver<Task>()
            .WhereRestrictionOn(x => x.Id).IsIn(courseIds)
            .Fetch(pt => pt.PersonalTaskReminders).Eager
            .TransformUsing(Transformers.DistinctRootEntity)
            .List<Task>();

答案 1 :(得分:1)

Xelibrion的解决方案是解决问题的正确方法。

要了解执行Fetch时结果重复的原因,您可以比较生成的SQL:

如果没有Fetch SELECT中的字段只是您的根实体Task字段。

Fetch PersonalReminder个实体的字段已添加到SELECT。因此,如果你有两个PersonalReminder寄存器用于相同的Task,你会在结果中得到两个寄存器,而DISTINCT子句不会删除它们(因为实际返回的寄存器是不同的,因为它们包含PersonalReminder字段。)

使用和不使用TransformUsing生成的SQL完全相同,但NH处理返回的寄存器以删除重复项。