我正在使用搜索页面,用户可以在搜索条件中使用通配符*
。通配符可以放在字符串的开头或结尾处。由于我需要将几个字段应用于此,我认为扩展方法是最好的方法。我提出的代码目前有效,但不适用于IQueryable
。
public static class Helper
{
public static IEnumerable<string> MyExtMethod(this IEnumerable<string> items, string searchString)
{
var searchType = -1;
if(searchString.IndexOf("*") == -1) //No wildcard
{
searchType = 0;
}
else if(searchString.IndexOf("*") == 0 && searchString.LastIndexOf("*") == searchString.Length - 1)//start and end
{
searchType = 1;
}
else if(searchString.IndexOf("*") == 0)//ends with
{
searchType = 2;
}
else if(searchString.LastIndexOf("*") == searchString.Length - 1) //starts with
{
searchType = 3;
}
var search = searchString.Replace("*", "");
foreach(var i in items)
{
switch(searchType)
{
case 0: yield return i;
break;
case 1: if(i.Contains(search))
yield return i;
break;
case 2: if(i.EndsWith(search))
yield return i;
break;
case 3: if(i.StartsWith(search))
yield return i;
break;
}
}
}
}
我只使用L2E Contains
,StartsWith
,EndsWith
已经支持的字符串操作和扩展方法。这可以转换为与实体一起使用吗?如果是这样,需要做什么?感谢。
编辑: 如果可能的话,我希望能够这样使用它:
db.SomeTable.Where(s => s.SomeField.MyExtMethod(somestring));
参考来源的奖励积分。
答案 0 :(得分:3)
EF使用IQueryable<T>
- 而不是IEnumerable<T>
所以这样的事情应该做:
public static class Helper
{
public static IQueryable<Table> SearchText(
this IQueryable<Table> q,
string searchString
)
{
var searchType = -1;
if(searchString.IndexOf("*") == -1)
{
searchType = 0; // No wildcard
}
else if(searchString.IndexOf("*") == 0 &&
searchString.LastIndexOf("*") == searchString.Length - 1)
{
searchType = 1; // start and end
}
else if(searchString.IndexOf("*") == 0)
{
searchType = 2; // ends with
}
else if(searchString.LastIndexOf("*") == searchString.Length - 1)
{
searchType = 3; // starts with
}
var search = searchString.Replace("*", "");
switch(searchType)
{
default:
case 0: return q.Where( o => o == search );
case 1: return q.Where( o => o.Text.Contains( search ) );
case 2: return q.Where( o => o.Text.EndsWith( search ) );
case 3: return q.Where( o => o.Text.StartsWith( search ) );
}
}
}
Table.Text
是您要搜索的属性。
然后你可以像这样使用它:
IQueryable<Table> q = dbContext.Table;
var matches = q.SearchText( searchString ).ToList();
答案 1 :(得分:0)
我在internet周围找到了一些基本代码,并稍微修改了它,以便我可以使用它。
public static class LinqExtensions
{
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));
}
public 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";
textLength = value.Length;
}
var stringType = typeof(string);
return stringType.GetMethod(methodName, new Type[] { stringType });
}
}