如何Linqify这个查询
本文关键字:查询 Linqify 如何 | 更新日期: 2023-09-27 18:27:40
我当前有一个Linq查询:
return this.Context.StockTakeFacts
.OrderByDescending(stf => stf.StockTakeId)
.Where(stf => stf.FactKindId == ((int)kind))
.Take(topCount)
.ToList<IStockTakeFact>();
目的是返回StockTakes的topCount的每个事实,但相反,我可以看到我只会得到事实的topCount数量。
我如何Linq ify这个查询来实现我的目标?
我可以用两个查询来获得topCount StockTakeId,然后做一个"中间",但我想知道Linq可能有什么技巧。
这就是我想要打败的。请注意,这实际上更多的是关于学习,而不是无法找到解决方案。我也关心性能,不是这些查询,但总的来说,我不想只是简单地做一些事情,发现它在幕后很糟糕。比如在我下面的第二个查询中,contains子句的惩罚是什么?
List<long> stids = this.Context.StockTakes
.OrderByDescending(st => st.StockTakeId)
.Take(topCount)
.Select(st => st.StockTakeId)
.ToList<long>();
return this.Context.StockTakeFacts
.Where(stf => (stf.FactKindId == ((int)kind)) && (stids.Contains(stf.StockTakeId)))
.ToList<IStockTakeFact>();
这个怎么样?
return this.Context.StockTakeFacts
.OrderByDescending(stf => stf.StockTakeId)
.Where(stf => stf.FactKindId == ((int)kind))
.Take(topCount)
.Select(stf=>stf.Fact)
.ToList();
如果我已经正确理解了你想要的东西,那么:
return this.Context.StockTakes
.OrderByDescending(st => st.StockTakeId)
.Take(topCount)
.Join(
this.Context.StockTakeFacts,
st => st.StockTakeId,
stf => stf.StockTakeId,
(st, stf) => stf)
.OrderByDescending(stf => stf.StockTakeId)
.ToList<IStockTakeFact>();
以下是我的尝试,主要使用查询语法并使用两个独立的查询:
var stids =
from st in this.Context.StockTakes
orderby st.StockTakeId descending
select st.StockTakeId;
var topFacts =
from stid in stids.Take(topCount)
join stf in this.Context.StockTakeFacts
on stid equals stf.StockTakeId
where stf.FactKindId == (int)kind
select stf;
return topFacts.ToList<IStockTakeFact>();
正如其他人所建议的,你想要的是加入。因为联接扩展有太多的参数,它们可能会有点令人困惑——所以我在执行联接时更喜欢查询语法——例如,如果顺序错误,编译器会出错。到目前为止,Join比过滤器更可取,这不仅是因为它阐明了数据是如何连接在一起的,而且出于性能原因,因为它在数据库中使用时使用索引,在linq中使用时对对象使用散列。
您应该注意,我在第二个查询中调用Take
是为了限制在第二次查询中使用的topCount
stid。我本可以在stids
查询的选择行上使用into
(即查询延续)来组合这两个查询,而不是使用两个查询。但这会造成将其限制为topCount
项的混乱。另一种选择是把stids
查询放在括号里,然后调用它的Take
。相反,把它分成两个查询对我来说似乎是最干净的
每当我认为编译器可以推断类型时,我通常会避免指定泛型类型;然而,IStockTakeFact
几乎可以肯定是一个接口,无论实现它的具体类型是什么,它都可能包含在this.Context.StockTakeFacts;
中,这就需要在ToList
调用上指定泛型类型。通常,我会在ToList
调用中省略泛型类型参数——这似乎是我个人品味的一个元素,你的可能会有所不同。如果this.Context.StockTakeFacts
已经是List<IStockTakeFact>
,则可以安全地省略ToList
调用上的泛型类型。