将Expression <func>选择器绑定到linq查询

时间:2016-01-13 13:09:15

标签: c# linq

我正在使用一个将linq表达式转换为事件查询的库。 (的StreamInsight)。

我需要解决这个问题:

给定一些值,以及一个组合值的表达式。

var a = new[] { "a", "b", "c" };
var b = new[] { "x", "y", "z" };
Expression<Func<string, string, string>> combine = (x, y) => x + ":" + y;

我需要将combine函数绑定到以下查询,同时仍然保持表达式语法。

var query =
    from f in a
    from g in b
    select combine(f, g);

query.Dump();

不幸的是,这个linq语句的目标应用程序不支持原始格式的Func<string, string, string>,因为查询是在运行时解释的。

我收到此错误:其他信息:Microsoft Complex Event Processing LINQ提供程序不支持以下表达式:'Invoke(value(System.Func`3 ...

如果我可以像以前一样重现表达式,我想我会解决问题:

var query =
    from f in a
    from g in b
    select x + ":" + y;

我想将查询的select部分作为Expression<Func<...参数传递给函数。

我试过这个,显然效果不好:

var query =
    a.SelectMany(a1 => b, (x, y) => new { x, y })
     .Select(_ => combine(_.x, _.y));

我已经简化了这个问题,但作为参考,真正的查询看起来像这样:

        var ms =
            requestStream
                .AlterEventLifetime(
                    _ => _.StartTime - TimeSpan.FromMilliseconds(10000),
                    _ => _.EndTime + TimeSpan.FromMilliseconds(10000) - _.StartTime)
                .SelectMany(requestData => responseStream
                    .AlterEventLifetime(
                        _ => _.StartTime - TimeSpan.FromMilliseconds(10000),
                        _ => _.EndTime + TimeSpan.FromMilliseconds(10000) - _.StartTime),
                    (requestData, responseData) => new {requestData, responseData})
                .Where(@t => @t.requestData.CorrelationTicketId == @t.responseData.CorrelationTicketId)
                .Where(@t => @t.requestData.CorrelationTicketId > 0
                             && @t.requestData.SuccessFailureCode != 3001)
                .Select(@t => expression(@t.requestData, @t.responseData));

3 个答案:

答案 0 :(得分:4)

您必须先编译表达式,然后才能将其用作函数:

var a = new[] { "a", "b", "c" };
var b = new[] { "x", "y", "z" };

Expression<Func<string, string, string>> combine = (x, y) => x + ":" + y;
var fu = combine.Compile();
var query =
        from f in a
        from g in b
        select fu(f, g);

答案 1 :(得分:0)

HimBromBeere的回答将起作用,如果你只是将它用于react-routerIEnumerable<string>的内存a来源,那么它就是那个。< / p>

否则,虽然它仍然适用于b,但它会通过将相关字符串拉入内存而不是将表达式推送到提供程序以便它可以成为SQL查询等来实现。 / p>

要处理您想要的IQueryable<string> IQueryable<string>

IQueryable<string>

(在var query = a.AsQueryable().SelectMany(_ => b, combine); 上运行时,这会成为一种稍微昂贵的IEnumerable<string>方式,这是另一种写出HimBromBeere给出的答案的方式。

答案 2 :(得分:-1)

补充说明:

Expression<Func<T>>是未编译的表达式树。如果您要将它发送给需要解析表达式树并转换它们(而不是仅运行代码)的提供程序,例如Entity Framework,则需要使用它。

您的案例涉及一个确实需要这样做的提供者,而不是在使用之前编译表达式(当您尝试将该代码块与实际的StreamInsight源重用时不起作用)您最好简单地调用{{ 1}}在模拟数组上,如下:

AsQueryable()

我还建议你对IQStreamable接口提供程序和扩展方法(来自StreamInsight)的实际工作方式进行一些研究,因为我不认为裸数组是模拟事件流的最佳选择。