2017-04-07 145 views
0

我正在使用Microsoft的Dynamic Linq(System.Linq.Dynamic)庫在運行時生成一些查詢。這對我來說很好,但對於一個特定的情況。使用outerIt生成動態Linq查詢

簡化方案 - 我試圖查詢所有具有用戶選擇的某些特定標籤且其餘額大於某個數字的索賠。

static void Main(string[] args) 
    { 
     var claims = new List<Claim>(); 
     claims.Add(new Claim { Balance = 100, Tags = new List<string> { "Blah", "Blah Blah" } }); 
     claims.Add(new Claim { Balance = 500, Tags = new List<string> { "Dummy Tag", "Dummy tag 1" } }); 

     // tags to be searched for 
     var tags = new List<string> { "New", "Blah" }; 
     var parameters = new List<object>(); 
     parameters.Add(tags); 

     var query = claims.AsQueryable().Where("Tags.Any(@0.Contains(outerIt)) AND Balance > 100", parameters.ToArray()); 
    } 

public class Claim 
{ 
    public decimal? Balance { get; set; } 
    public List<string> Tags { get; set; } 
} 

這個查詢拋出一個錯誤:

An unhandled exception of type 'System.Linq.Dynamic.ParseException' occurred in System.Linq.Dynamic.dll Additional information: No property or field 'Balance' exists in type 'String'

動態LINQ解析器似乎試圖找到在標籤上,而不是索賠對象上的平衡性能。

  • 我試圖玩弄outerIt,innerIt,它關鍵字在動態的LINQ但沒有它似乎工作。
  • 更改序列的工作方式,但這不是我的選擇,因爲在實際應用中,過濾器,操作員和模式將是動態的(由最終用戶配置)。
  • 裝箱括號()中的條件也沒有幫助。
  • 解決方法 - 爲每個選中的標記創建一個簡單的包含條件。 Tags.Contains(「New」)或Tags.Contains(「Blah」)等等。但是在真實的應用程序中,它會導致對每個條件進行非常複雜/差勁的查詢並且會導致性能下降。

我可能會錯過某些東西,或者這可能是庫中的一個錯誤。

我真的很感激,如果有人能幫助我這個。

+0

你在哪裏學到這樣的語法,任何文檔鏈接? –

+0

這是我的出發點:https://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library。然後有其他從我從哪裏得到的引用問題:http://stackoverflow.com/questions/37740409/c-sharp-dynamiclinq-where-clause-with-any –

+0

據我所知,大多數關鍵字適用於Linq/EF應該爲動態linq提供一些語法差異。 –

回答

1

找到一個/ ParseAggregate中的錯誤...推動itouterIt如果有多個級別,則返回不起作用。該代碼假設itouterIt在重置之前不會被第三方更改(技術上該代碼不可重入)。您可以嘗試使用System.Linq.Dynamic的其他變體(其中有兩個或三個變體)。可能有些變體已經修復它。

或者您也可以從鏈接的網站採取的代碼並重新編譯它你的代碼中(在最後的「原始」 System.Linq.Dynamic是一個CS文件),你可以修補它是這樣的:

Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) 
{ 
    // Change starts here 
    var originalIt = it; 
    var originalOuterIt = outerIt; 
    // Change ends here 

    outerIt = it; 
    ParameterExpression innerIt = Expression.Parameter(elementType, elementType.Name); 
    it = innerIt; 
    Expression[] args = ParseArgumentList(); 

    // Change starts here 
    it = originalIt; 
    outerIt = originalOuterIt; 
    // Change ends here 

    MethodBase signature; 
    if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1) 

我已經在項目的github中建議的錯誤修復中打開了一個問題。

+0

我會用修補程序修補文件,並讓您知道是否可以解決該問題。非常感謝。 –

+0

這是有效的。謝謝你,你救了我幾周的勞累。我不太瞭解整個環境中修復的性質,所以我不確定這個修復的影響是什麼。在github repo上記錄缺陷是否有意義,以便它在任何即將發佈的版本中得到修復? –

+0

@AmanvirSinghMundra 2分鐘前我已經對我的帖子進行了更新:*我已經在項目的github中建議的錯誤修復中打開了一個問題。* – xanatos