如何确定IQueryable表达式是否需要其他处理

时间:2009-08-31 21:17:57

标签: sql sql-server linq-to-sql client-side

通过额外的处理,我的意思是除了Transact SQL的标准LINQ to SQL转换(以及可能的解决方法)

我有两个问题,我希望能够获得一些洞察力和/或一些适当的链接或Google术语,以便在我找不到任何内容时查找更多信息。归结为我想知道将要执行的IQueryable表达式何时/如何确定某些表达式结果需要运行“客户端”,这意味着LINQ表达式无法直接转换Transact SQL返回整个结果。

This与我的帖子/代码有关。

情况1

string.Format()未转换为Transact SQL。我可以接受,但我猜我只是在寻找一些关于如何检测Expression是否能够完全转换为Transact SQL的建议。

LINQ表达式:

from h in HistoryData
select new { NewData = string.Format( "New Data: {0}", h.hisData ) };

提供者上下文SQL:

SELECT [t0].[hisData] AS [arg0]
FROM [HistoryData] AS [t0]

我的解决方法:目前,我正在使用DataContext.GetCommand()方法,然后查看Transact SQL并搜索[arg0]。显然不理想,所以我一直在寻找一个更强大的机制(可能会发现一个ExpressionTree访问者的东西?)

情况2

在某些情况下使用第三级运算符似乎会返回一些Transact SQL,它显然会对其应用一些post / client处理以获得正确的值。在下面的示例中,我在LINQPad的上下文中运行(因此可以使用Dump()扩展方法)。当第三级运营商参与比赛时,似乎有两种情况需要进行后期处理:

  1. 当使用布尔变量和布尔字段时(下面的var testBool ...表达式)和
  2. 当使用两个变量时,无论其类型如何,都会查询 no 数据库字段(下面的第二个testNumber表达式)。
  3. 这种情况让我感到惊讶,需要客户端处理。因此,除了学习如何正确检测表达式何时需要在正常的Transact SQL之外进行额外处理之外,如果有人知道为什么L2S不能像其他情况那样执行简单的CASE语句,更重要的是可能的解决方法可以用来避免任何“客户端”处理,这将是伟大的!

    LINQ表达式:

    var before9_1_2009 = DateTime.Today < new DateTime( 2009, 9, 1 );
    var fiveThousand = 5000;
    var tenThousand = 10000;
    var testNumber = 
        Profiles.Where( p => p.pAuthID == "111111111" )
                .Select( p => new { Number = before9_1_2009 ? fiveThousand : p.pKey } );
    var cmd = GetCommand( testNumber );
    cmd.CommandText.Dump( "Number Property: Works (i.e. evaluates on SQL Server)" );
    
    var testString = 
        Profiles.Where( p => p.pAuthID == "111111111" )
                .Select( p => new { String = before9_1_2009 ? "StringConstant" : p.pAuthID } );
    cmd = GetCommand( testString );
    cmd.CommandText.Dump( "String Property: Works (i.e. evaluates on SQL Server)" );
    
    var testBool = 
        Profiles.Where( p => p.pAuthID == "111111111" )
                .Select( p => new { Boolean = boolExp ? true : p.pProcessed } );
    cmd = GetCommand( testBool );
    cmd.CommandText.Dump( "Boolean Property: Has NULL AS [EMPTY] - Post Processing Needed" );
    
    testNumber = 
        Profiles.Where( p => p.pAuthID == "111111111" )
                .Select( p => new { Number = before9_1_2009 ? fiveThousand : tenThousand } );
    cmd = GetCommand( testNumber );
    cmd.CommandText.Dump( "Number Property (using two constants): Has NULL AS [EMPTY] - Post Processing Needed" );
    

    提供程序上下文SQL(按顺序): ▪数字属性:工作(即在SQL Server上评估)

    SELECT 
        (CASE 
            WHEN @p1 = 1 THEN @p2
            ELSE [t0].[pKey]
         END) AS [Number]
    FROM [Profile] AS [t0]
    WHERE [t0].[pAuthID] = @p0
    

    ▪字符串属性:工作(即在SQL Server上评估)

    SELECT 
        (CASE 
            WHEN @p1 = 1 THEN CONVERT(NVarChar(255),@p2)
            ELSE [t0].[pAuthID]
         END) AS [String]
    FROM [Profile] AS [t0]
    WHERE [t0].[pAuthID] = @p0
    

    ▪布尔属性:具有NULL AS [EMPTY]

    SELECT NULL AS [EMPTY]
    FROM [Profile] AS [t0]
    WHERE [t0].[pAuthID] = @p0
    

    ▪Number属性(使用两个常量):具有NULL AS [EMPTY]

    SELECT NULL AS [EMPTY]
    FROM [Profile] AS [t0]
    WHERE [t0].[pAuthID] = @p0
    

    我的解决方法:同样,我正在使用DataContext.GetCommand()方法,然后查看Transact SQL并搜索NULL AS [EMPTY]。想知道是否有任何其他“魔术字符串”出现在无法在服务器上运行的表达式代码中......如上所述,我正在寻找一种正确,更强大的方法来检测这些情况。

1 个答案:

答案 0 :(得分:0)

快速观察:

  1. 你在哪里宣布boolExp变量?
  2. Number属性(使用两个常量):2 var个对象返回不明确的类型。 (对于第一个数字情况p.pKey定义的类型)