使用nHibernate对特定的Future <t>查询和集合有困难。</t>

时间:2011-07-30 11:11:08

标签: nhibernate

为了举例,我删除了非查询和非必要数据,只是为了弄清楚如何在这里进行初始查询。

我有这样的模型结构。

class Path {
  Guid Id { get; protected set; }
  IList<Step> Steps { get; set; }
  void AddStep(Step entity) {
    // write up bidirectional association
  }
}
class Step {
  Guid Id { get; protected set; }
  Path Path { get; set; }
  // other data irreleveent
}

现在假设50000步,每步有5000步...我确实意识到我不想立刻归还所有这些步骤。但限制我的查询获取并不是我真正的问题。

以下是我尝试使用的确切查询。我得到了例外......

  

NHibernate.QueryException:重复别名:lpStep     ----&GT; System.ArgumentException:已添加具有相同键的项目。

我不完全确定如何处理这种情况。如果我在Fetch查询中使用了Path,那么我会从NHibernate Profiler中得到Select+N个错误。

我确实启用了批处理 - 但据我所知,这只适用于插入,而不是检索。但在任何情况下,我都会收回这些错误而不确定如何处理它。有什么想法吗?

using (var Transaction = Session.BeginTransaction()) {

                Path lpPath = null;
                Step lpStep = null;

                var lpPaths = Session.QueryOver<Path>(() => lpPath)
                    .Take(50)
                    .Future<Path>();

                var lpSteps = Session.QueryOver<Step>(() => lpStep)
                    .JoinAlias(() => lpPath.Steps, () => lpStep)
                    .Where(o => o.Path.Id == lpPath.Id)
                    .Take(12)
                    .Future<Step>();

                Transaction.Commit();

                foreach (var path in lpPaths) {
                    Console.WriteLine("{0} fetched {1} Steps",
                        path.Id, path.Steps.Count);
                }
            }

我基本上想说..

  

选择(50)路径,作为单独的选择但是同一行程的一部分,选择属于先前选择的路径的第一个(12)步骤。

但是如果我使用平坦的连接,我会得到110行,而我希望有2个表,50个行中的1个,600行中的1个。

有人可以向我解释我做错了吗?

请注意,我可以进行一些小的更改并运行查询,但它不是'优化'。我可以获得我想要的数据,但它需要多次旅行和延迟加载。我可以很容易地优化实际的Path选择,但是那些是Step。如果我只是从lpSteps查询中取出限制性where子句,它只返回前12个步骤,而不是为每个完成的查询返回12个步骤。

我查看了Future<T>上的其他一些堆栈溢出帖子,发现它们看起来很像这样。所以我不明白为什么它不起作用。我怀疑这是怎么回事......

  

lpPaths 运行。

     

lpSteps 尝试运行,首先成功。

     

lpSteps 然后再次尝试运行,发现它无法重新定义lpPaths。

     

Apocolypse

我真的希望比我聪明的人能够以绝对最优的方式来启发我。

1 个答案:

答案 0 :(得分:0)

我真的不明白你的用例是什么。为什么你只需要每个路径的前12个步骤?那些批处理的步骤

怎么样?
IList<Guid> pathIds;
while ((pathIds = QueryOver.For<Path>()
     .Where(...)
     .Projection(path => path.Id)
     .SetmaxResults(100)).Count > 0)
{

    int batch = 0;
    const int batchsize = 600;
    IList<Step> steps;
    while ((steps = Session.QueryOver<Step>()
        .Where(step => step.Path.Id).In(pathIds)
        .Where(step => step. ...)
        .SetFirstResult(batch * batchsize)
        .Take(batchsize)
        .List<Step>()).Count > 0)
    {
        DoSomething(steps);
        batch++;
    }
}