sql-server - LINQ to SQL 不跳过导致多个 SQL 语句

标签 sql-server linq linq-to-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 的一些推理。

如果您just Take,则查询翻译器仅使用top。如果加入子集合破坏了基数,Top10 将不会给出正确的答案。因此,查询翻译器不会加入子集合(而是重新查询子集合)。

如果您跳过并获取,则查询翻译器会在父行上执行一些 RowNumber 逻辑...这些行号让它占用 10 个父行,即使实际上每个父行有 50 条记录 parent 有 5 个 child 。

如果您Skip(0) 并Take,则“Skip”将被译者作为非操作删除 - 就像您从未说过“Skip”一样。

从您所在的位置(称为“跳过”和“采取”)到“简单的解决方法”,这将是一个艰难的概念飞跃。我们需要做的是强制翻译发生在翻译器无法将 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, 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);

这会产生以下查询:

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

关于sql-server - LINQ to SQL 不跳过导致多个 SQL 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/857807/

相关文章:

sql-server - R:[unixODBC][驱动程序管理器]无法打开 lib 'SQL Server':找不到文件

sql - 锯齿图案局部最大值的每日总计

c# - 将 SQL 转换为 Linq 查询

linq-to-sql - 使用 IoC、依赖注入(inject)、工作单元的 Linq to SQL 的存储库模式

c# - 将 IQueryable 集合导出到 Excel

java - 从servlet执行oracle查询结果错误

sql - 查找多个列的重复项独占 ID 列

c# - 当不满足Where子句时,LINQ扩展方法是否可以使用new().Value创建新的KeyValuePair

c# - 如何使 Entity Framework 存储过程异步?

c# - 在 LINQ-To-SQL 中使用返回表达式的方法