2

我正在尝试手动组合表达式树以实现某种程度的模块化,这似乎暗示我使用标准的 linq 运算符。该代码本质上创建了一个表达式树,它使用一个表达式来决定调用另外两个表达式中的哪一个。其他表达式之一需要一个额外的参数,该参数本身是使用另一个表达式获得的。此参数用于获取多个值,但对于每次访问,检索参数的表达式都会重复。我已经包含了代码和输出以更好地解释:

public void Test() {
    var parameters = ProjectionOne.Parameters;
    Expression<Func<Foo, bool>> isType = f => f.TypeId == 1;
    Expression<Func<Foo, Satellite>> satSelector = f => f.Satellites.Single();
    var satelliteSelector = Expression.Invoke(satSelector, parameters[0]);
    var test = Expression.Lambda<Func<Foo, Bar>>(
        Expression.Condition(
            Expression.Invoke(isType, parameters[0]),
            Expression.Invoke(ProjectionOne, parameters[0]),
            Expression.Invoke(ProjectionTwo, parameters[0], satelliteSelector)), parameters);
}

public Expression<Func<Foo, Bar>> ProjectionOne {
    get {
        return foo => new Bar() {
            Id = foo.Id
        };
    }
}

public Expression<Func<Foo, Satellite, Bar>> ProjectionTwo {
    get {
        return (foo, sat) => new Bar() {
            Id = foo.Id,
            Start = sat.Start,
            End = sat.End
        };
    }
}

当我在数据库上运行此查询时,生成的 SQL 如下:

SELECT [t0].[value], [t0].[value2] AS [Start], [t0].[value3] AS [End], [t0].[Id] AS [Id]
FROM (
    SELECT 
        (CASE 
            WHEN [t0].[TypeId] = @p0 THEN 1
            WHEN NOT ([t0].[TypeId] = @p0) THEN 0
            ELSE NULL
         END) AS [value], (
        SELECT [t2].[Start]
        FROM [dbo].[Satellite] AS [t2]
        WHERE [t2].[Id] = [t0].[Id]
        ) AS [value2], (
        SELECT [t2].[End]
        FROM [dbo].[Satellite] AS [t2]
        WHERE [t2].[Id] = [t0].[Id]
        ) AS [value3], [t0].[Id]
    FROM [dbo].[Foo] ) AS [t0]

问题是重复的子选择。一个检索“开始”值,而另一个检索“结束”值。如果它们都从单个子选择中检索出来会更好。如何更改表达式树的构造以强制执行此操作?此外,我确实了解执行此查询有更简单的方法,但是它是此处未显示的更大框架的一部分,只能通过能够从大量可重用表达式中手动组装表达式树来实现。

4

1 回答 1

1

我怀疑您已经做了所有可以做的事情(因为您已经在使用投影,引擎选择将其表示为单独的子选择)。

我能想到的唯一其他事情是(例如)使用表值 UDF(通过数据上下文)来获取开始/结束 - 看看它是否将其展平到查询中。

您是否对查询进行了概要分析并与您的首选布局进行了比较?配置文件很可能是相同的(即 TSQL 优化器已经处理了它)。在这种情况下,不必过分担心。

于 2009-02-24T08:42:04.590 回答