为了举例,我删除了非查询和非必要数据,只是为了弄清楚如何在这里进行初始查询。
我有这样的模型结构。
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
我真的希望比我聪明的人能够以绝对最优的方式来启发我。
答案 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++;
}
}