【问题标题】:Dynamic library (System.Linq.Dynamic) SQL LIKE Operator动态库 (System.Linq.Dynamic) SQL LIKE 运算符
【发布时间】:2018-11-16 10:47:38
【问题描述】:

有人在这里发过类似的问题How Dynamic library (System.Linq.Dynamic) support LIKE Operator?

但这并不是我想要的。该帖子中提到的 Contains 运算符仅在 SQL "%SOMETHING%" 中执行此操作。但是 SQL 中的 LIKE 运算符可以做到这一点 "SOME%THING"。动态 LINQ 是否有类似的运算符?如果没有,是否有解决方案?也许使用正则表达式?还有一个字符通配符吗?例如。 “SOM$THING”返回“SOMETHING”或“SOM3THING”

编辑:我正在开发一个 WPF 应用程序,它应该读取 XML 格式的日志文件。每个元素包含 34 个字段。因此,我没有编写很长的 WHERE,而是使用 System.Reflection.PropertyInfo 来迭代每个字段以编写查询,然后使用 System.Linq.Dynamic 执行它。

Edit2:我已经编辑了代码,以便观众更容易阅读。

这里有一些代码:

示例 1: prop.Name = "FirstName", paramterString = "Ke%in", 返回 "Kevin", “开尔文”... 示例 2: prop.Name = "FirstName", paramterString = "Ke$in", 返回 "Kevin", “科林”……

var query = "";
StringBuilder sb = new StringBuilder();
foreach (var prop in stringProps)
{
    sb.Append($"({prop.Name} != null And {prop.Name}.Contains({parameterString})");
}
query = sb.ToString().Substring(0, sb.Length - 4);
filteredData = filteredData.Where(query);

其中一个要求是实现 SQL LIKE 运算符,因此用户可以使用类似这样的东西来获得他们想要的结果:FirstName LIKE 'SOME%THING'

【问题讨论】:

  • 你能把你的项目限制在 MS SQL Server 上吗?然后你可以extendDynamic LINQ 来支持SQLMethods.Like
  • 很遗憾这是不可能的,因为数据是通过读取 XML 文件导入的。
  • 在您链接的帖子上,有一个answer 建议使用ContainsStartsWitsEndsWith 的组合。这对你有用吗?您还可以使用 Regex-Like,如 here 所示。但是纯 LIKE 是 LInq 不提供的。
  • 这就是我害怕的。所以我使用 String.IndexOf() 来创建我自己的 LIKE 运算符。如果有人可以查看代码甚至更好地对其进行优化,我将不胜感激。代码发布在答案中。
  • 开始听起来好像这与 SQL 无关。如果您只想为 LINQ to Objects 实现 LIKE 样式运算符,我建议将 SQL LIKE 模式转换为 RE,并使用 C# 正则表达式处理。

标签: c# sql linq dynamic-linq


【解决方案1】:

由于 Dynamic Linq 库中没有 LIKE 运算符,因此我创建了自己的版本。代码不是很漂亮,但它确实有效。希望有人可以对其进行优化或提出更好的方法。

public string ParseWildcardInParameterString(string parameter, string propertyName)
{
    string stringWithWildcard = parameter;
    if (parameter.Contains("%") || parameter.Contains("$"))
    {
        stringWithWildcard = parameter;
        string[] substrings = parameter.Split(new Char[] { '%', '$' }, StringSplitOptions.RemoveEmptyEntries);
        string[] wildcards = ParseWildcards(parameter);
        if (substrings.Any())
        {
            StringBuilder sb = new StringBuilder();
            int substringsCount = substrings.Length;
            for (int i = 0; i < substringsCount; i++)
            {
                if (!substrings[i].EndsWith("\\"))
                {
                    int index = parameter.IndexOf(substrings[i]);
                    if (i < substringsCount - 1)
                    {
                        index = parameter.IndexOf(substrings[i + 1], index + 1);
                        if (index > -1)
                        {
                            string secondPart = wildcards[i].Equals("%") ?
                                $"{propertyName}.IndexOf(\"{substrings[i + 1]}\", {propertyName}.IndexOf(\"{substrings[i]}\") + \"{substrings[i]}\".Length) > -1" :
                                $"{propertyName}.IndexOf(\"{substrings[i + 1]}\", {propertyName}.IndexOf(\"{substrings[i]}\") + \"{substrings[i]}\".Length + 1) == {propertyName}.IndexOf(\"{substrings[i]}\") + \"{substrings[i]}\".Length + 1";
                            sb.Append($"({propertyName}.IndexOf(\"{substrings[i]}\") > -1 And {secondPart}) And ");
                        }
                    }
                }
            }
            stringWithWildcard = sb.Remove(sb.Length - 5, 5).Append(") Or ").ToString();
        }
    }
    return stringWithWildcard;
}

private string[] ParseWildcards(string parameter)
{
    IList<string> wildcards = new List<string>();
    foreach (var chararcter in parameter.ToCharArray())
    {
        if (chararcter.Equals('%') || chararcter.Equals('$'))
        {
            wildcards.Add(chararcter.ToString());
        }
    }
    return wildcards.ToArray();
}

【讨论】:

    【解决方案2】:

    如果System.Linq.Dynamic.Core 中的Like 功能对你有用,你能试试吗?

    代码示例如下:

    var dynamicFunctionsLike1 = context.Cars.Where(config, "DynamicFunctions.Like(Brand, \"%a%\")");

    完整示例,请参阅ConsoleAppEF2.1.1/Program.cs

    【讨论】:

    • 我收到一个错误“DynamicFunctions is not valid”之类的。
    • 您使用的是 EF 2.x 吗?
    • 不,我只使用标准的 Dynamic Linq。此代码实际执行过滤器。 filtersData = filtersData.Where(query, parameters.ToArray());
    猜你喜欢
    • 2014-10-29
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多