Динамический обратный слэш linq в предложении where - PullRequest
0 голосов
/ 25 сентября 2018

Я использую System.Linq.Dynamic для запроса сущностей с динамическими выражениями «где».Я запрашиваю объект, который имеет свойство "newValue" типа строки.Примерное значение будет следующим: "{\" ProcessId \ ": 764, \" ProcessLength \ ": 1000}".Я не могу использовать ==, потому что я хочу найти все попадания, где свойство содержит «ProcessId: 764», независимо от остальной части строки.Дело в том, что сохраненная строка содержит управляющий знак "\" и двойные кавычки, и я не могу понять, что именно должно нравиться ..

dbContext.Processes.Where("@newValue.Contains(\"ProcessId\":764\")") приносит ошибку, однако dbContext.Processes.Where("@newValue.Contains(\":764\")") работает правильно.Я предполагаю, что это должно быть что-то с обратной косой чертой или двойными кавычками в моем запросе, но я не могу понять это самостоятельно ..

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

@ HeyJude Спасибо за усилия, но я все еще не могу заставить их работать.Это как-то пошло не так, и теперь я не могу даже получить правильные строки, содержащие только номер ProcessId ..

Позвольте мне дать вам более подробное описание моей настройки.В базе данных есть таблица со столбцом «NewValue», я использую этот столбец для хранения json-строки текущего (на момент создания строки в таблице) представления некоторого объекта, например объекта Process .Таким образом, в столбце хранится, например, строка {"ProcessId": 904, "ProcessLength": 1000} .Чтобы получить эти данные из базы данных, я создаю коллекцию записей таблицы: 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?

0 голосов
/ 02 октября 2018

Здесь следует отметить две вещи:

  1. Если вы знаете во время компиляции столбец, который должен быть запрошен (т. Е. newValue), просто используйте стандартный Linq: var list = items.Where(i => i.NewValue.Contains("904")).ToList().

  2. Если вы хотите использовать dyanmic Linq, вам обычно нужно применить Where к некоторому столбцу, например, Where("SomeColumn.Contains("something")") или Where("SomeColumn.Contains(@0)", new string[] {"something"}).

    Итак, в вашем случае это должно работать: items.Where("newValue.Contains(\"904\")").

    Выполнение Where("@newValue.Contains("something")") на самом деле не имеет смысла, так как @newValue будет проанализирован как строковый литерал.См. Также комментарий к похожему вопросу.

Вот краткий пример:

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();
}
...