【问题标题】:Dynamic linq backslash in where clausewhere 子句中的动态 linq 反斜杠
【发布时间】:2019-08-19 05:18:36
【问题描述】:

我使用 System.Linq.Dynamic 来查询具有动态“where”表达式的实体。我正在查询具有字符串类型属性“newValue”的对象。示例值为:“{\"ProcessId\":764, \"ProcessLength\":1000}"。 我不能使用 == 因为我想找到属性包含“ProcessId:764”的所有命中,而不管字符串的其余部分。问题是,存储的字符串包含转义符号“\”和双引号,我无法弄清楚它到底应该是什么样的......

dbContext.Processes.Where("@newValue.Contains(\"ProcessId\":764\")") 带来错误,但 dbContext.Processes.Where("@newValue.Contains(\":764\")") 工作正常。我想它一定是我的查询中带有反斜杠或双引号的东西,但我自己无法弄清楚..

【问题讨论】:

  • 如果我没记错的话,这个.Contains(\":764\") 表示它会在newValue 中寻找这个":764"
  • 您可能需要双反斜杠才能在最终的Contains 字符串中得到一个。
  • @Simo 没错,它在 newValue 中寻找“:764”。 @NetMage 我尝试了双重反冲,这很有意义,但令人惊讶的是它没有找到任何匹配的项目。我尝试了dbContext.Processes.Where("@newValue.Contains(@newValue.Contains(\"ProcessId\\\":764\")\")\",但它会导致 System.Linq.Dynamic.ParseException 出现消息“')' 或 ',' 预期"

标签: c# linq escaping dynamic-linq system.linq.dynamic


【解决方案1】:

这里有两点需要注意:

  1. 如果您在编译时知道应该查询的列(即newValue),只需使用标准 Linq:var list = items.Where(i => i.NewValue.Contains("904")).ToList()

  2. 如果您确实想使用动态 Linq,您通常想要的是在某些列上应用 Where,例如Where("SomeColumn.Contains("something")"),或Where("SomeColumn.Contains(@0)", new string[] {"something"})

    所以,在你的情况下,这应该有效:items.Where("newValue.Contains(\"904\")")

    执行Where("@newValue.Contains("something")") 并没有真正意义,因为@newValue 将被解析为字符串文字。另请参阅comment 的类似问题。

这里是一个简单的例子:

public static void Main(string[] args)
{
    var items = new [] 
    { 
       new { Id = "1", Title = "ProcessId: 123"}, 
       new { Id = "4", Title = "ProcessId: 456"}, 
       new { Id = "7", Title = "ProcessId: 789"}, 
    }.ToList();

    // returns null, because the string "Title" doesn't contain the string "7"
    var res1 = items.Where("@0.Contains(\"7\")", new string[] {"Title"}).FirstOrDefault();     

    // works - returns the 3rd element of the array
    var res2a = items.Where("Title.Contains(@0)", new string[] {"ProcessId: 789"}).FirstOrDefault();                 
    var res2b = items.Where("Title.Contains(\"ProcessId: 789\")").FirstOrDefault();
}

【讨论】:

    【解决方案2】:

    @HeyJude 感谢您的努力,但我仍然无法正常工作。它以某种方式出错了,现在我什至无法获取仅给出 ProcessId 编号的正确行..

    让我更详细地描述我的设置。在数据库中有一个列“NewValue”的表,我使用此列存储某些对象的当前(用于在表中创建行的时间)表示的 json 字符串,例如对象进程。因此,该列存储例如 {"ProcessId":904,"ProcessLength":1000} 的字符串。为了从 db 中获取这些数据,我创建了表记录的集合:var items = (from l in db.JDE_Logs join u in db.JDE_Users on l.UserId equals u.UserId join t in db.JDE_Tenants on l.TenantId equals t.TenantId where l.TenantId == tenants.FirstOrDefault().TenantId && l.Timestamp >= dFrom && l.Timestamp <= dTo orderby l.Timestamp descending select new //ExtLog { LogId = l.LogId, TimeStamp = l.Timestamp, TenantId = t.TenantId, TenantName = t.TenantName, UserId = l.UserId, UserName = u.Name + " " + u.Surname, Description = l.Description, OldValue = l.OldValue, NewValue = l.NewValue });。然后我查询它以查找给定 ProcessId 编号的匹配行,例如query = "@NewValue.Contains(\"904,)\")"; items = items.Where(query); 这应该取回 NewValue 列包含查询字符串的所有记录,但这不起作用。它编译并“工作”,但没有获取数据或仅获取 904 稍后出现在字符串中的那些记录。听起来很愚蠢,但这就是事实。

    查询字符串应该是什么样子来获取包含"ProcessId":904的所有记录?

    【讨论】:

    • 一些事情:1. 如果您在编译时知道应该查询的列(即NewValue),只需使用简单的Linq:var list = items.Where(i =&gt; i.NewValue.Contains("904")).ToList()2. 如果您确实想使用动态 Linq,那么正如我在回答中所写,应该是:items.Where("NewValue.Contains(\"904\")")
    • 我希望它作为动态 linq 查询的一部分的原因是我可以在单个参数中发送所有查询条件,为了使用标准 linq 查询它,我为此值添加了第二个参数。但老实说,我现在可以看到,有时我非常专注于一些我看不到更简单但有效的解决方案的想法。谢谢你的绝妙想法,我终于让它工作了:)
    • 顺便说一句,我想将您的帖子标记为我的问题的解决方案,但不幸的是它是评论,我不能。也许你可以把它放在单独的答案中?
    • 我编辑了我的原始答案以包含附加信息
    猜你喜欢
    • 2021-08-12
    • 2010-10-25
    • 1970-01-01
    • 2023-03-29
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多