Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server LINQ to SQL Take w/o Skip导致多个SQL语句_Sql Server_Linq_Linq To Sql - Fatal编程技术网

Sql server LINQ to SQL Take w/o Skip导致多个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 } }

我有一个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
        }
}
这将导致执行一条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