使用正则表达式搜索时的通配符 (*,!)

Wildcard (*,!) on search using Regex

我是 MVC 新手,我想在数据库上执行通配符 (*, !) 搜索。这是我使用 Regex 所做的:

控制器:

using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using WebApplication1.Models;


namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {

        CrossWord_dbEntities db = new CrossWord_dbEntities();

        public ActionResult Index(string searching)
        {
            var regEx = WildcardToRegex(searching);
            return View(db.tbl_values.Where(x => Regex.IsMatch(x.Name, regEx, RegexOptions.Singleline)));//.ToList()));
        }

public static string WildcardToRegex(string pattern)
        {
            return "^" + Regex.Escape(pattern).
            Replace("\*", ".*").
            Replace("\?", ".") + "$";
        }

    }
}

查看:

@model IEnumerable<WebApplication1.Models.tbl_values>

<br /><br />
@using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
@Html.TextBox("searching") <input type="submit" value="Search" />
}

<table class="table table-striped">
    <thead>
        <tr>
            <th>Results</th>
        </tr>
    </thead>
    <tbody>
        @if (Model.Count() == 0)
        {
            <tr>
                <td colspan="3" style="color:red">
                    No Result 
                </td>
            </tr>
        }
        else
        {
            foreach (var item in Model)
            {
                <tr>
                    <td>
                        @item.Name
                    </td>
                </tr>
            }
        }

    </tbody>

</table>

使用上面的代码,当我 运行 我在行中得到一个异常:“@if (Model.Count() == 0)”

LINQ to Entities 无法识别方法 'Boolean IsMatch(System.String, System.String, System.Text.RegularExpressions.RegexOptions)' 方法,并且无法将此方法转换为存储表达式。

我需要做什么来解决这个问题?

我尝试在控制器的 return 行中添加 "ToList()"

return View(db.tbl_values.Where(x => Regex.IsMatch(x.Name, regEx, RegexOptions.Singleline).ToList()));

但我在这一行得到了相同的期望。

谢谢阿米尔

异常消息很简单:在 LINQ to Entities 模式下执行查询时,Regex.IsMatch() 方法没有等效的 SQL 语句。您需要在 Where 子句之前放置 AsEnumerable()ToList() 方法以将 DbContext 实体具体化为 IEnumerable 对象:

public class HomeController : Controller
{
    CrossWord_dbEntities db = new CrossWord_dbEntities();

    public ActionResult Index(string searching)
    {
        var regEx = WildcardToRegex(searching);
        return View(db.tbl_values.AsEnumerable().Where(x => Regex.IsMatch(x.Name, regEx, RegexOptions.Singleline)));
    }
}

由于您的 WildcardToRegex 方法仅适用于 IEnumerable 或 LINQ to Objects,您可以尝试添加 this solution 中描述的其他方法以与 IQueryable 一起使用实体如下:

public static IQueryable<TSource> WhereLike<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> valueSelector, string value, char wildcard)
{
    return source.Where(BuildLikeExpression(valueSelector, value, wildcard));
}

private static Expression<Func<TElement, bool>> BuildLikeExpression<TElement>(Expression<Func<TElement, string>> valueSelector, string value, char wildcard)
{
    if (valueSelector == null) throw new ArgumentNullException("valueSelector");

    var method = GetLikeMethod(value, wildcard);

    value = value.Trim(wildcard);
    var body = Expression.Call(valueSelector.Body, method, Expression.Constant(value));

    var parameter = valueSelector.Parameters.Single();
    return Expression.Lambda<Func<TElement, bool>>(body, parameter);
}

private static MethodInfo GetLikeMethod(string value, char wildcard)
{
    var methodName = "Equals";

    var textLength = value.Length;
    value = value.TrimEnd(wildcard);
    if (textLength > value.Length)
    {
        methodName = "StartsWith";
        textLength = value.Length;
    }

    value = value.TrimStart(wildcard);
    if (textLength > value.Length)
    {
        methodName = (methodName == "StartsWith") ? "Contains" : "EndsWith";
    }

    var stringType = typeof(string);
    return stringType.GetMethod(methodName, new[] { stringType });
}

然后对任何实施 IQueryable 的实体使用 WhereLike 方法,如下例所示:

// usage example
using (CrossWord_dbEntities db = new CrossWord_dbEntities())
{
    var query = db.tbl_values.WhereLike(x => x.Name, "[search text]", "[wildcard character]");
}

类似问题:

linq to entities doesn't recognize a method