简体   繁体   English

使用outerIt生成动态Linq查询

[英]Generate Dynamic Linq query using outerIt

I am using Microsoft's Dynamic Linq (System.Linq.Dynamic) library to generate some queries at run time. 我正在使用Microsoft的Dynamic Linq(System.Linq.Dynamic)库在运行时生成一些查询。 This has worked great for me, but for one specific scenario. 这对我来说非常有效,但是对于一种特定情况而言。

Simplified scenario - I am trying to query all claims which have some specific tags that the user has selected and whose Balance is greater than some number. 简化方案-我正在尝试查询所有索赔,这些索赔具有用户选择的某些特定标签并且其余额大于某个数字。

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; }
}

This query throws an error: 该查询引发错误:

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' System.Linq.Dynamic.dll中发生类型为'System.Linq.Dynamic.ParseException'的未处理异常附加信息:类型'String'中不存在属性或字段'Balance'

Dynamic linq parser seems to try to find the Balance property on the Tag and not on the Claim object. 动态linq解析器似乎试图在Tag而不是Claim对象上找到Balance属性。

  • I have tried to play around with outerIt, innerIt, It keywords in Dynamic Linq but none of it seems to work. 我试过在Dynamic Linq中使用externalIt,innerIt,It关键字,但是似乎都不起作用。
  • Changing the sequence works, but that's not an option for me, since in the real application the filters, operators and patterns will be dynamic (configured by end user). 更改顺序是可行的,但这不是我的选择,因为在实际应用中,过滤器,运算符和模式将是动态的(由最终用户配置)。
  • Boxing the conditions in brackets (), also doesn't help. 将条件放在方括号()中也无济于事。
  • Workaround - create a simple contains condition for every Tag selected eg Tags.Contains("New") OR Tags.Contains("Blah") etc.. But in the real application it results in a really complex / bad query for each condition and kills the performance. 解决方法-为选定的每个标签创建一个简单的包含条件,例如,Tags.Contains(“ New”)或Tags.Contains(“ Blah”)等。但是在实际应用中,这会导致对每个条件的查询非常复杂/错误破坏了表演。

I might be missing something or this could be a bug in the library. 我可能丢失了一些东西,或者这可能是库中的错误。

I would really appreciate if someone could help me with this. 如果有人可以帮助我,我将非常感激。

Found a/the bug in ParseAggregate ... The pushing of itouterIt and back doesn't work if there are multiple levels. 发现A /臭虫ParseAggregate ...的推动itouterIt和回来,如果有多个级别不起作用。 The code supposes that the it and outerIt won't be changed by a third party before being reset (technically the code isn't reentrant). 该代码假定itouterIt不会在重置之前被第三方更改(从技术上讲该代码不可重入)。 You can try with other variants of System.Linq.Dynamic (there are like two or three variants out of there). 您可以尝试使用System.Linq.Dynamic其他变体(那里有两个或三个变体)。 Probably some variants have already fixed it. 可能有一些变体已将其修复。

Or you can take the code from the linked site and recompile it inside your code (in the end the "original" System.Linq.Dynamic is a single cs file) and you can patch it like this: 或者,您可以从链接的站点获取代码,然后在代码内部对其进行重新编译(最后,“原始” 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)

I've already opened an Issue with the suggested bug fix in the github of the project. 我已经在项目的github中打开了一个带有建议的错误修复的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM