我正在开发能够将过滤器应用于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表达式。但怎么办呢?天知道。
高度赞赏。
答案 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。