如何在编译时不知道对象类型时如何构建LINQ查询

时间:2009-02-03 13:57:46

标签: c# sql linq

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

控件通过跟随字段

知道它应该操作的对象字段
    /// <summary>
    /// Method to get compared column from object
    /// </summary>
    public Expression<Func<T, int>> GetColumnMethod;

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

我们使用类似

的代码执行过滤

... if(selectedValue ==“&lt; =”)                     predicate = predicate.And(c =&gt; method(c)&lt; = val);                 if(selectedValue ==“&lt;”)                     predicate = predicate.And(c =&gt; method(c)&lt; val);

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

当然,CLR不知道如何为代理人制作SQL。

如果只有C#可以在转换为SQL之前编译表达式,但是我不知道怎么做它。

像Expression.Compile这样的变态(无论我整天尝试过什么棘手的方式 - 我已经记不起来了......没有任何帮助)

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

高度赞赏。

4 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

它无效。基本上你的LINQ查询是有效的C#代码,所以它编译得很好但是在运行时期间在LINQ to SQL提供程序范围之外的任何事情上都会失败。

在这里阅读更多内容:

<强> “Cannot call methods on DateTime”, and other limitations

答案 2 :(得分:0)

如果只是选择要在查询中使用的特定字段,则应该能够使用Expression.Compile“perversion”来执行此操作。但这可能是很多工作。你可以通过编译你现在拥有的东西并使用Reflector对输出来看看C#编译器生成的代码是什么样的。

您可以将查询拆分为两部分 - 一部分转换为SQL并在服务器上运行,一部分使用您的GetColumnMethod并在内存中运行第一部分的数据输出?

答案 3 :(得分:0)

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