Sql server LINQ to SQL Take w/o Skip导致多个SQL语句
我有一个LINQ到SQL查询:Sql server LINQ to SQL Take w/o Skip导致多个SQL语句,sql-server,linq,linq-to-sql,Sql Server,Linq,Linq To Sql,我有一个LINQ到SQL查询: from at in Context.Transaction select new { at.Amount, at.PostingDate, Details = from tb in at.TransactionDetail select new { Amount = tb.Amount, Description = tb.Desc } }
from at in Context.Transaction
select new {
at.Amount,
at.PostingDate,
Details =
from tb in at.TransactionDetail
select new {
Amount = tb.Amount,
Description = tb.Desc
}
}
这将导致执行一条SQL语句。一切都很好
但是,如果我尝试从此查询返回已知类型,即使它们与匿名类型具有相同的结构,我会为顶层执行一条SQL语句,然后为每个“子”集执行一条额外的SQL语句
有没有办法让LINQtoSQL发出一条SQL语句并使用已知类型
编辑:我必须有另一个问题。当我在LINQPad中插入一个非常简单(但仍然是层次结构)的查询版本,并使用新创建的已知类型(只有2或3个成员)时,我得到了一条SQL语句。我会发布和更新,当我知道更多
编辑2:这似乎是由于Take中的错误造成的。有关详细信息,请参见下面的答案。我没有机会尝试此方法,但鉴于匿名类型不是LINQ的一部分,而是C#构造,我想知道您是否可以使用:
from at in Context.Transaction
select new KnownType(
at.Amount,
at.PostingDate,
Details =
from tb in at.TransactionDetail
select KnownSubType(
Amount = tb.Amount,
Description = tb.Desc
)
}
显然,细节需要是一个IEnumerable集合
在这方面,我可能有很多不同的想法,但这至少会给你一个新的思路去追求,这不会有什么坏处,所以请原谅我的漫无边际。我现在确定这是一个可怕的错误造成的。结果证明,匿名与已知类型之间的差异不是原因。真正的原因是采取行动 在1条SQL语句中生成以下结果:
query.Skip(1).Take(10).ToList();
query.ToList();
但是,下面展示了每个父行一个sql语句的问题
query.Skip(0).Take(10).ToList();
query.Take(10).ToList();
有人能想出一些简单的解决办法吗
编辑:我想出的唯一解决办法是检查我是否在第一页(即跳过(0)),然后打两个电话,一个是Take(1),另一个是Skip(1)。Take(pageSize-1)并将列表添加到一起。首先-Take bug的一些原因 如果您只取,查询转换器只使用top。如果加入子集合打破了基数,Top10将不会给出正确答案。因此,查询转换器不加入子集合(而是为子集合重新查询) 如果您跳过并执行,则查询转换器将在父行上使用一些行号逻辑。。。这些行数让它需要10个家长,即使这实际上是50条记录,因为每个家长有5个孩子 如果您跳过(0)并执行,则翻译器会将跳过作为非操作删除-就像您从未说过跳过一样 这将是一个艰难的概念性飞跃,从您现在的位置(调用Skip and Take)到“简单的解决方法”。我们需要做的是强制翻译发生在翻译器无法将跳过(0)作为非操作删除的位置。我们需要调用Skip,并在以后提供跳过的号码
DataClasses1DataContext myDC = new DataClasses1DataContext();
//setting up log so we can see what's going on
myDC.Log = Console.Out;
//hierarchical query - not important
var query = myDC.Options.Select(option => new{
ID = option.ParentID,
Others = myDC.Options.Select(option2 => new{
ID = option2.ParentID
})
});
//request translation of the query! Important!
var compQuery = System.Data.Linq.CompiledQuery
.Compile<DataClasses1DataContext, int, int, System.Collections.IEnumerable>
( (dc, skip, take) => query.Skip(skip).Take(take) );
//now run the query and specify that 0 rows are to be skipped.
compQuery.Invoke(myDC, 0, 10);
这就是我们获胜的地方
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2
这是可行的,但是为了调用ToList,我不得不使用IEnumerable而不是仅仅使用IEnumerable。在我的测试用例中,它也快了半秒。回答很好。这里的问题不就是用第一个
ToList()
调用SQL执行,然后第二个ToList()
调用第一个结果中现在内存中的每个项的查询吗?
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2