我是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
答案 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]");
}
类似问题: