2017-04-07 82 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