используя регулярное выражение / Удалить специальные символы с linq to sql - PullRequest
1 голос
/ 28 мая 2010

Как я могу использовать регулярные выражения с linq to sql в приложении asp.net mvc (C #)?

В столбцах моей таблицы MSSQL (Products) есть некоторые специальные символы, такие как (, -% ',.....).

При поиске продукта мне нужно искать без этих специальных символов.

Например: у меня есть слово продукта (ABC-Camp's / One), когда япоиск "abccamp", он должен тянуть продукт.

Я пытаюсь запрос как:

from p in _context.pu_Products
     where p.User_Id == userId && p.Is_Deleted == false
     && p.Product_Name.ToLower().Contains(text.ToLower())
     select new Product
     {
           ProductId = p.Product_Id,
           ProductName = p.Product_Name.Replace("’", "").Replace("\"", ""),
           RetailPrice = p.Retail_Price ?? 0M,
           LotSize = p.Lot_Size > 0 ? p.Lot_Size ?? 1 : 1,
           QuantityInHand = p.Quantity_In_Hand ?? 0  
     }

Но мне нужно искать без каких-либо специальных символов ...

Ответы [ 3 ]

0 голосов
/ 28 мая 2010

Вот 2 варианта:

  1. Использование метода SqlMethods.Like (рекомендуется)
  2. Использование метода AsEnumerable для извлечения записей и использования регулярных выражений или чего-либо подобного на стороне клиента в памяти (дороже)

Переходя к варианту № 1 выше, вы можете сделать что-то вроде этого:

string searchTerm = "abccamp";
string pattern = "%"
                 + String.Join("%", searchTerm.Select(c => c.ToString()).ToArray())
                 + "%";

var query = from x in y
            where SqlMethods.Like(x, pattern)
            select x;

Адаптируя его к вашему запросу, вы, вероятно, будете использовать что-то похожее на SqlMethods.Like(p.Product_Name, pattern) вместо p.Product_Name.ToLower().Contains(text.ToLower()).

РЕДАКТИРОВАТЬ: , как упомянуто в комментариях, этот подход может не дать точных результатов, так как между каждым символом существует подстановочный знак, чтобы заменить специальные символы. Другой возможный подход - использовать _ вместо % для учета одного символа. Недостатком является то, что у вас может быть несколько специальных символов подряд, и для повторений потребуется подстановочный знак, что возвращает нас к тому, с чего мы начали. С SqlMethods.Like вы можете использовать те же вещи, что и для TSQL LIKE . Это включает в себя классы символов с диапазонами и классы отрицанных символов, так что вы также можете использовать [!/@ ] вместо % в String.Join.

Проблема с использованием _ заключается в том, что вы не можете сделать один символ необязательным, как если бы вы использовали регулярное выражение. Шаблон a_b_c_d не соответствует «abcd», так как каждый _ должен соответствовать символу между каждой буквой. Другими словами, это будет соответствовать "a! B $ c @ d". Возможно, вы можете использовать оба в предложении where: ... where x == searchTerm || SqlMethods.Like(x, pattern), где pattern такое же, как и раньше, но с использованием _ вместо % в методе String.Join.

Кроме того, убедитесь, что у вас есть некоторая логика if / else, проверяющая searchTerm, чтобы определить, что делать, если ввод пуст или состоит из одного символа, который даст %x% и может быть нежелательным и соответствовать многим строки.

0 голосов
/ 29 мая 2010

Нет, вы не можете, нет преобразования из регулярного выражения в SQL-запрос.

Что вы можете сделать, это, возможно, использовать операцию ExecuteQuery <> (используя запеченный литерал SQL) в DataContext и установить функцию .Net (UDF) в базу данных, которая выполняет регулярное выражение (нет требуется небезопасный материал, так как Regex определен в основных библиотеках).

Таким образом, вы можете делать все это на сервере.

Чтобы упростить и избавиться от большинства встроенного SQL, вы можете использовать GetCommand из DataContext и передать свой текущий оператор Linq со всеми, кроме условия Regex. Получите текст обратно и добавьте регулярное выражение в предложение where (опять же, вам все еще нужен UDF регулярного выражения в базе данных).

Я также не уверен, что вызов метода string.Replace будет также правильно переводиться в SQL - в этом случае вам может понадобиться использовать UDF для этого также в операторе select.

0 голосов
/ 28 мая 2010

Эх, я думаю, что вы должны проверить все символы в записях. потому что это не может быть с текстом. как это.

Linq2Sql:

IQueryable<Product> iQueryable = from p in _context.pu_Products
                                 where p.User_Id == userId && p.Is_Deleted == false
                                 select p;

Match match = Regex.Match(text, "(?<Str>[\\w])+")
if (match.Success) {
    foreach (Capture capture in match.Groups["Str"].Captures) {
        string value = capture.Value;
        iQueryable = iQueryable.Where(p => p.Product_Name.Contains(value));
    }
}

var products = from p in iQueryable
               select new Product
               {
                    ProductId = p.Product_Id,
                    ...
               }

Сгенерированный SQL:

WHERE Product_Name LIKE '%a%' AND Product_Name LIKE '%b%' AND...
...