【问题标题】:How can I build LINQ query when object type is not known at compile-time在编译时不知道对象类型时如何构建 LINQ 查询
【发布时间】:2009-02-03 13:57:46
【问题描述】:

我正在开发能够将过滤器应用于 LinqDataSource 对象的 Web 自定义控件。它是通用控件,因为它应该与特定类型的对象一起操作。

控件通过以下字段知道它应该操作对象的哪个字段

    /// <summary>
    /// Method to get compared column from object
    /// </summary>
    public Expression<Func<T, int>> GetColumnMethod;

(我转移到从对象类型中获取适当字段的方法)

我们用这样的代码进行过滤

... if (selectedValue == " 方法(c) method(c)

在 LINQ 到 SQL 转换发生之前,一切正常。 然后错误“方法'.....'没有支持的SQL转换。

当然,CLR 不知道如何为委托创建 SQL。

如果只有 C# 可以在转换为 SQL 之前编译表达式,但我不知道如何做到这一点。

Expression.Compile 之类的变态(无论我尝试了一整天的任何棘手方法 - 我已经无法全部记住它们......没有任何帮助)

但是......在运行时 CLR 已经知道我的对象的类型,因此它可以设法构建具有编译委托值的 SQL 表达式。但是怎么做呢?天知道。

帮助非常感谢。

【问题讨论】:

    标签: c# sql linq


    【解决方案1】:

    LINQ to SQL 提供程序负责将您的表达式树转换为有效的 T-SQL 语句。由于 C# 和 T-SQL 之间没有一对一的关系,因此表达式树越复杂,LINQ to SQL 翻译的可能性就越小。

    当您使用 lambda 表达式时,您必须决定是要编译它还是将其用作表达式树。如果您想将 lambda 用作表达式,那么您有责任确保表达式包含您的提供程序支持的函数和语法。

    【讨论】:

      【解决方案2】:

      这行不通。基本上,您的 LINQ 查询是有效的 C# 代码,因此可以正常编译,但在运行时在 LINQ to SQL 提供程序范围之外的任何内容上都会失败。

      在这里阅读更多:

      “Cannot call methods on DateTime”, and other limitations

      【讨论】:

        【解决方案3】:

        如果只是选择要在查询中使用的特定字段,您应该能够使用 Expression.Compile “perversion” 来做到这一点。但这可能需要做很多工作。您可能可以通过编译您现在拥有的内容并针对输出使用 Reflector 来查看 C# 编译器生成的代码是什么样子,从而抢占先机。

        您能否将查询分成两部分 - 一个被转换为 SQL 并在服务器上运行,另一个使用您的 GetColumnMethod 并针对第一部分输出的数据在内存中运行?

        【讨论】:

          【解决方案4】:

          没有用于任意委托的 SQL。如果 method(c) 可以表示为 lambda,您可以使用 Expression.Invoke 将 lambda 作为子表达式调用,但您需要自己构建表达式树,like so

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-08-08
            • 1970-01-01
            • 2013-12-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多