sql-server – LINQ to SQL Take w / o Skip导致多个SQL语句

前端之家收集整理的这篇文章主要介绍了sql-server – LINQ to SQL Take w / o Skip导致多个SQL语句前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个LINQ to 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语句.

有没有办法让LINQ to sql发出一个sql语句并使用已知类型?

编辑:我必须有另一个问题.当我将一个非常简单(但仍然是高级的)查询版本插入LINQPad并使用新创建的已知类型只有2或3个成员时,我确实得到了一个sql语句.当我知道更多时,我会发布和更新.

编辑2:这似乎是由于Take中的一个错误.请参阅下面的答案了解详情.

解决方法

首先 – Take bug的一些推理.

如果您只是Take,则查询翻译器只使用top.如果通过加入子集合来破坏基数,Top10将无法​​给出正确的答案.因此查询转换器不会加入子集合(而是重新查询子集合).

如果你跳过并接受,那么查询翻译器就会在父行上使用一些RowNumber逻辑…这些rownumber允许10个父母,即使由于每个父母有5个孩子,这实际上是50个记录.

如果你跳过(0)和Take,翻译器将非翻录作为非操作删除 – 就像你从未说过Skip一样.

这将是一个艰难的概念上的飞跃,从你所在的地方(称为Skip and Take)到“简单的解决方法”.我们需要做的是 – 强制转换发生在翻译者无法将Skip(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,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,10);

这会产生以下查询

SELECT [t1].[ParentID],[t2].[ParentID] AS [ParentID2],(
    SELECT COUNT(*)
    FROM [dbo].[Option] AS [t3]
    ) AS [value]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID]) AS [ROW_NUMBER],[t0].[ParentID]
    FROM [dbo].[Option] AS [t0]
    ) AS [t1]
LEFT OUTER JOIN [dbo].[Option] AS [t2] ON 1=1 
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2
ORDER BY [t1].[ROW_NUMBER],[t2].[ID]
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
-- @p2: Input Int (Size = 0; Prec = 0; Scale = 0) [10]
-- Context: sqlProvider(sql2005) Model: AttributedMetaModel Build: 3.5.30729.1

这就是我们赢的地方!

WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2

猜你在找的MsSQL相关文章