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

时间:2017-12-09 11:15:16

标签: asp.net-mvc search wildcard

我是MVC的新手,我想在数据库上执行Wildcard(*,!)搜索。这就是我使用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)'方法,并且此方法无法转换为商店表达式。

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

我试着在控制器的返回行中写入“ToList()”

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

但我在这一行得到同样的解释。

感谢Amir

1 个答案:

答案 0 :(得分:1)

异常消息很简单:在LINQ to Entities模式下执行查询时,Regex.IsMatch()方法没有等效的SQL语句。您需要在AsEnumerable()子句之前放置ToList()Where方法,以将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 });
}

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

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