Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.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
C# CompiledQuery与普通Linq SQL生成_C#_Entity Framework_Linq To Entities - Fatal编程技术网

C# CompiledQuery与普通Linq SQL生成

C# CompiledQuery与普通Linq SQL生成,c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,因此,我对访问SQLServer数据库的不同方法进行了一些分析。我编写了香草TSQL、编译查询和非编译Linq语句 正如预期的那样,性能按照相同的顺序进行,但在分析后两个时,我注意到一些奇怪的事情 CompiledQuery生成的SQL比普通的old语句生成的SQL要好得多 本地SQLExpress数据库;表称为“foreignTable”,列为int,主键(索引);ColumnB是一个随机整数 Func<testingDatabaseEntities1, int, int> Get

因此,我对访问SQLServer数据库的不同方法进行了一些分析。我编写了香草TSQL、编译查询和非编译Linq语句

正如预期的那样,性能按照相同的顺序进行,但在分析后两个时,我注意到一些奇怪的事情

CompiledQuery生成的SQL比普通的old语句生成的SQL要好得多

本地SQLExpress数据库;表称为“foreignTable”,列为int,主键(索引);ColumnB是一个随机整数

Func<testingDatabaseEntities1, int, int> GetByPK = CompiledQuery.Compile((testingDatabaseEntities1 ft, int key) 
  => (ft.foreignTable.Where(x => x.ColumnA == key).FirstOrDefault().ColumnB));
对于生成的代码来说,这并不可怕

但当我做简单的Linq陈述时:

entity.foreignTable.Where(x => x.ColumnA == searchForMe).FirstOrDefault().ColumnB
它产生:

SELECT 
[Limit1].[C1] AS [C1], 
[Limit1].[ColumnA] AS [ColumnA], 
[Limit1].[ColumnB] AS [ColumnB], 
[Limit1].[FKColumn] AS [FKColumn]
FROM ( SELECT TOP (1) 
    [Extent1].[ColumnA] AS [ColumnA], 
    [Extent1].[ColumnB] AS [ColumnB], 
    [Extent2].[FKColumn] AS [FKColumn], 
    1 AS [C1]
    FROM  [dbo].[foreignTable] AS [Extent1]
    LEFT OUTER JOIN (SELECT 
      [Table_2].[FKColumn] AS [FKColumn], 
      [Table_2].[SomeText] AS [SomeText]
      FROM [dbo].[Table_2] AS [Table_2]) AS [Extent2] ON [Extent1].[ColumnA] = [Extent2].[FKColumn]
    WHERE [Extent1].[ColumnA] = @p__linq__7
)  AS [Limit1]
这太糟糕了


因此,我想问题是:是否有可能给实体提供与编译查询相同数量的常规Linq?编译查询正在做额外的工作,因为预计您将多次使用该查询。如果这就是您所追求的,那么只需坚持编译查询即可

在此特定场景中,您需要执行以下操作:

entity.foreignTable
    .Where(x => x.ColumnA == searchForMe)
    .Select(x=>x.ColumnB)
    .FirstOrDefault();

这并不完全相同,但它肯定会使查询更符合您的期望(只检索ColumnB)。执行FirstOrDefault将为您提供实例,因此.ColumnB发生在linq2sql查询之后。这也会导致行为上的差异,因为您的版本会因为null引用而失败,而此新查询将提供ColumnB的默认值(null或特定值,具体取决于ColumnB的定义)。

您正在比较的查询不相同。第一个编译后的查询只返回一个属性,不返回其他任何属性。它永远不会返回任何不同的结果。第二个返回一个实体实例,您可以取消引用该实例,然后访问其属性。当查询执行时,它无法知道您打算只查看一个属性

从非编译查询中获取相同SQL的一种方法(未经测试)是投影到匿名类型:

var b = (from e in entity.foreignTable.
         where ColumnA == searchForMe
         select new 
         {
            ColumnB = e.ColumnB
         }).FirstOrDefault().ColumnB;

如果找不到元素,则由于null引用而引发。我在我的答案上发布的版本不会有这种行为;这是故意的。我在跟踪他的问题中询问的行为。你的答案表现不同。好的。像OP示例那样使用.FirstOrDefault+列访问的编译查询有点奇怪,所以我不确定这是否真的引发了错误。我会重构编译后的版本,以使用您的版本或我的版本,即使这些版本更长,但它们会让您更清楚地了解其意图。
var b = (from e in entity.foreignTable.
         where ColumnA == searchForMe
         select new 
         {
            ColumnB = e.ColumnB
         }).FirstOrDefault().ColumnB;