Entity framework Linq表达式树-串联值数组
我目前正在使用一个.net核心(vnext)解决方案,该解决方案使用linq和实体框架核心 我们使用Microsoft.Linq.Translations将计算列定义存储为lambda表达式,以便在需要时将它们注入到语句中。计算定义的示例如下所示:Entity framework Linq表达式树-串联值数组,entity-framework,linq,linq-to-sql,lambda,linq-to-entities,Entity Framework,Linq,Linq To Sql,Lambda,Linq To Entities,我目前正在使用一个.net核心(vnext)解决方案,该解决方案使用linq和实体框架核心 我们使用Microsoft.Linq.Translations将计算列定义存储为lambda表达式,以便在需要时将它们注入到语句中。计算定义的示例如下所示: private static readonly CompiledExpression<Model, string> fullNameExpression = aTranslation<Model>.Expres
private static readonly CompiledExpression<Model, string> fullNameExpression =
aTranslation<Model>.Expression(e => e.FullName, e => $"{e.FirstName} {e.LastName} ({e.Code})");
因此,如果我将计算定义更改为以下内容(注意,我只是手动构建字符串,而不是使用string.format:
private static readonly CompiledExpression<Model, string> fullNameExpression =
aTranslation<Model>.Expression(e => e.FullName, e => e.FirstName + " " + e.LastName + "(" + e.Code + ")");
因此,除了更改编写/定义计算定义的方式外,我正在尝试编写一个层,该层接受使用字符串格式linq表达式编写的定义,并将该表达式替换为第二种类型(如字符串连接)
我通过截取字符串格式表达式并构建成员和常量表达式的列表/数组(即。
名字,
" ",
姓,
" ("
等等
我尝试使用字符串concat方法,通过循环遍历值并计算左表达式和右表达式,但这最终导致了其他一些不起作用的结果:
.Call System.String.Concat(
.Call System.String.Concat(
.Call System.String.Concat(
.Call System.String.Concat(
$e.FirstName,
" "),
$e.LastName),
" ("),
$e.Code)
现在,我被困在如何转换表达式列表以生成这种表达式的问题上:
.Lambda #Lambda1<System.Func`2[Model,System.Boolean]>(Model $e) {
.Call ($e.FirstName + " " + $e.LastName + " (" + $e.Code + ")").Contains("Bob")}
好吧,我想出来了 @usr的评论促使我进一步深入研究语法树,看看代码是如何编译的。我在“视图->其他窗口->语法可视化工具”下使用了VS2015中内置的语法可视化工具 当分解期望结果的标准linq表达式时,这表明在幕后这是编译成一个看起来很奇怪的二进制运算符 最初,我尝试将string.concat调用替换为:
BinaryExpression.Add(concatArgs[0], concatArgs[1])
但是,这导致了以下错误:
未为类型“System.String”定义二进制运算符Add
和“System.String”
这让我想到了这篇文章/帖子:
对于建议的过载:
基本上,在幕后,所有这些最终都会转换为string.concat调用,但是使用BinaryExpression.Add方法似乎允许linq在运行时解决这个问题,并且只使用一个对string.concat的调用?可能是“params object[]”
无论如何,将我的GenerateStringConcat方法更改为以下方法已经达到了目的:
private Expression GenerateStringConcat(Expression left, Expression right)
{
return BinaryExpression.Add(left, right, typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }));
}
好吧,我想出来了 @usr的评论促使我进一步深入研究语法树,看看代码是如何编译的。我在“视图->其他窗口->语法可视化工具”下使用了VS2015中内置的语法可视化工具 当分解期望结果的标准linq表达式时,这表明在幕后这是编译成一个看起来很奇怪的二进制运算符 最初,我尝试将string.concat调用替换为:
BinaryExpression.Add(concatArgs[0], concatArgs[1])
但是,这导致了以下错误:
未为类型“System.String”定义二进制运算符Add
和“System.String”
这让我想到了这篇文章/帖子:
对于建议的过载:
基本上,在幕后,所有这些最终都会转换为string.concat调用,但是使用BinaryExpression.Add方法似乎允许linq在运行时解决这个问题,并且只使用一个对string.concat的调用?可能是“params object[]”
无论如何,将我的GenerateStringConcat方法更改为以下方法已经达到了目的:
private Expression GenerateStringConcat(Expression left, Expression right)
{
return BinaryExpression.Add(left, right, typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }));
}
在有效的查询中手动编写表达式。然后,反编译程序集(或使用Roslyn online)以查看C#编译器生成的表达式树。这是一个可以使用的模板。发布您尝试过的代码,以便我们可以尝试调整它。在有效的查询中手动编写表达式。然后,反编译程序集(或使用Roslyn online)查看C#编译器生成的表达式树。这是一个可以使用的模板。发布您尝试过的代码,以便我们可以尝试调整它。
.Lambda #Lambda1<System.Func`2[Model,System.Boolean]>(Model $e) {
.Call ($e.FirstName + " " + $e.LastName + " (" + $e.Code + ")").Contains("Bob")}
Expression expr = GenerateStringConcat(concatArgs[0], concatArgs[1]);
for(int i = 2; i < concatArgs.Count; i++)
expr = GenerateStringConcat(expr, concatArgs[i]);
private Expression GenerateStringConcat(Expression left, Expression right) {
return Expression.Call(
null,
typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }),
new[] { left, right });
}
BinaryExpression.Add(concatArgs[0], concatArgs[1])
private Expression GenerateStringConcat(Expression left, Expression right)
{
return BinaryExpression.Add(left, right, typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }));
}