使用正则表达式/删除linq到sql的特殊字符

时间:2010-05-28 18:28:01

标签: .net regex linq-to-sql

如何在asp.net mvc(C#)应用程序中使用linq to sql的正则表达式?

我的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 :(得分:0)

呃,我想你必须检查记录中的所有字符。因为它不能用文字。像这样。

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...

答案 1 :(得分:0)

以下是两个选项:

  1. 使用SqlMethods.Like method(推荐)
  2. 使用AsEnumerable method下拉记录并在客户端使用正则表达式等内存(更昂贵)
  3. 使用上面的选项#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,其中_与以前相同,但在{{1}中使用%代替String.Join方法。

    此外,请确保在searchTerm周围进行一些if / else逻辑检查,以确定如果输入为空或由单个字符组成,该字符将产生%x%并且可能不是希望并匹配许多行。

答案 2 :(得分:0)

不,你不能,没有从正则表达式到SQL查询的转换。

你可以做的是在DataContext上使用ExecuteQuery<>操作(使用烘焙的SQL文字),并将.Net函数(UDF)安装到执行正则表达式的数据库中(不需要不安全的东西,正如核心库中定义的正则表达式。)

这样你就可以在服务器上完成所有工作。

为了简化和摆脱嵌入式SQL的大多数,您可以使用DataContext中的GetCommand,并使用除Regex条件之外的所有内容传递当前的Linq语句。获取文本,并将Regex添加到where子句中(同样,您仍需要在数据库中使用正则表达式UDF。)

我也不确定string.Replace方法调用是否会正确地转换为SQL - 在这种情况下,您可能还需要在select语句中使用UDF。