像LINQ to Entities中的运算符或使用通配符一样

Who*_*nja 8 c# linq linq-to-entities

我正在使用LINQ 2实体.以下是问题:

string str = '%test%.doc%' 
.Contains(str) // converts this into LIKE '%~%test~%.doc~%%'
Run Code Online (Sandbox Code Playgroud)

预期转换:LIKE'%test%.doc%'

如果它是LINQ 2 SQL,我可以使用SqlMethods.Like,因为有人在我之前的问题中回答了它.但是现在因为我使用L2E而不是L2S,我需要其他解决方案.

BG1*_*100 16

SQL方法PATINDEX提供与LIKE相同的功能.因此,您可以使用SqlFunctions.PatIndex方法:

.Where(x => SqlFunctions.PatIndex("%test%.doc%", x.MySearchField) > 0)
Run Code Online (Sandbox Code Playgroud)


Evg*_*vgK 2

您可以尝试使用这篇文章,其中作者介绍了如何在 LINQ to Entities 中使用通配符构建 LIKE 语句。

编辑:由于原始链接现已失效,这里是原始扩展类(根据评论中的 Jon Koeter)和使用示例。

扩大:

public static class LinqHelper
{
    //Support IQueryable (Linq to Entities)
    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));
    }

    //Support IEnumerable (Linq to objects)
    public static IEnumerable<TSource> WhereLike<TSource>(this IEnumerable<TSource> sequence, Func<TSource, string> expression, string value, char wildcard)
    {
        var regEx = WildcardToRegex(value, wildcard);

        //Prevent multiple enumeration:
        var arraySequence = sequence as TSource[] ?? sequence.ToArray();

        try
        {
            return arraySequence.Where(item => Regex.IsMatch(expression(item), regEx));
        }
        catch (ArgumentNullException)
        {
            return arraySequence;
        }
    }

    //Used for the IEnumerable support
    private static string WildcardToRegex(string value, char wildcard)
    {
        return "(?i:^" + Regex.Escape(value).Replace("\\" + wildcard, "." + wildcard) + "$)";
    }

    //Used for the IQueryable support
    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 });
    }
}
Run Code Online (Sandbox Code Playgroud)

使用示例:

string strEmailToFind = "%@yahoo.com"

IQueryable<User> myUsers = entities.Users.WhereLike(u => u.EmailAddress, strEmailToFind, '%');
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望用户更习惯 Windows 资源管理器样式的通配符:

string strEmailToFind = "*@yahoo.com"

IQueryable<User> myUsers = entities.Users.WhereLike(u => u.EmailAddress, strEmailToFind, '*');
Run Code Online (Sandbox Code Playgroud)

  • 但是如何组合多个Where 子句呢?例如,要生成“WHERE FirstName LIKE 'A%' OR LastName LIKE 'A%'”? (2认同)
  • 不幸的是,该链接已失效。这就是为什么应避免仅链接答案的原因 (2认同)