2016-01-13 64 views
1

我正在使用將linq表達式轉換爲事件查詢的庫。 (的StreamInsight)。將表達式<Func>選擇器綁定到linq查詢

我需要解決這個問題:

鑑於一些值,並結合值的表達式。

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

我需要將組合函數綁定到以下查詢,同時仍保持表達式語法。

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

query.Dump(); 

不幸的是,這個LINQ語句中的目標應用程序不支持Func<string, string, string>在它的原始格式,因爲該查詢在運行時解釋。

我得到這個錯誤:附加信息:下面的表達不會被微軟複雜事件處理LINQ提供程序支持:「調用(值(System.Func`3 ...

我想我會解決如果我可以重現表達,因爲它本來的問題:

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

我想查詢的選擇部分傳遞到一個函數作爲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)); 
+0

'.SelectMany(a1 => b,combine)'工作嗎? – Rawling

+0

否,CS1929 '字符串[]' 不包含關於 '的SelectMany' 和最好的擴展方法過載「Queryable.SelectMany <字符串,字符串,字符串>(IQueryable的,表達> >,表達>)」需要類型的接收器‘的IQueryable ’ – Jim

+0

除此之外,我真的需要弄清楚如何將其綁定到的選擇,因爲我真實的場景有很多,其中條款也是如此。 – Jim

回答

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); 
+0

任何理由下來的? – HimBromBeere

+0

your're權利,這就是它所需要的。工作的魅力。我認爲這會導致相同的錯誤Func鍵<字符串,字符串,字符串>但它不」 – Jim

+0

啊表達式的生活,讓功能強大,這麼多學習一下吧,很好的回答雖然+1從我的身邊 –

-1

附加說明:

Expression<Func<T>>是一個未編譯的表達式樹。如果要將它發送給需要解析表達式樹並將其轉換(而不是僅運行代碼)的提供程序(如Entity Framework),則需要使用它。

您的情況涉及到一個提供者,確實需要這樣做,而不是在使用前編譯表達式(當您嘗試重用帶有實際StreamInsight源代碼的代碼塊時,這不起作用),您最好只需調用AsQueryable()在嘲笑陣列,像這樣:

// using function form of LINQ because it's more flexible 
// also, using the join because that's what your query does - a cartesian product 
var query = a.AsQueryable().Join(b.AsQueryable(), x => 0, x => 0, combine); 

我也建議你做一些調查,到IQStreamable接口提供和擴展方法(從的StreamInsight)是如何工作的,因爲我不認爲裸陣列是嘲笑事件流的最佳選擇。

+0

你不能調用像'結合表達式(F,G)'。 –

+0

編譯絕對是需要的。 Func <...不適用於流洞察提供程序。表達式 Jim

+0

@JonHanna我的錯。我使用LINQ的查詢形式,所以很少我忘記了你不能給它表達式。編輯+解釋。 –

0

HimBromBeere的答案將起作用,如果您只是將要使用內存IEnumerable<string>來源ab那麼這是一個值得去做的。

否則,當它仍然會與IQueryable<string>工作,它通過將拉動相關的字符串到內存中,而不是推式下降到供應商這樣做,以便它可以成爲一個SQL查詢等

爲了應對IQueryable<string>IQueryable<string>你會想:

var query = a.AsQueryable().SelectMany(_ => b, combine); 

(當IEnumerable<string>運行這成爲做a.SelectMany(_ => b, combine.Compile());這是anothe的稍貴方式這是寫給HimBromBeere給出的答案的方式)。