LINQ 的通配符搜索

发布于 2024-07-25 14:07:37 字数 142 浏览 8 评论 0原文

我想知道是否可以使用 LINQ 进行通配符搜索。

我看到 LINQ 有 Contains、StartsWith、EndsWith 等。

如果我想要 %Test if%it work% 之类的东西,我该怎么做?

问候

I would like to know if it is possible to do a wildcard search using LINQ.

I see LINQ has Contains, StartsWith, EndsWith, etc.

What if I want something like %Test if%it work%, how do I do it?

Regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

梦醒时光 2024-08-01 14:07:38

对于 Entity Framework Core 2.0LIKE 运算符(2017 年 8 月宣布):

var query = from e in _context.Employees
                    where EF.Functions.Like(e.Title, "%developer%")
                    select e;

For Entity Framework Core 2.0 there is LIKE operator (announced in August 2017):

var query = from e in _context.Employees
                    where EF.Functions.Like(e.Title, "%developer%")
                    select e;
夜清冷一曲。 2024-08-01 14:07:38

看着问题

如果我想要%Test if%it work%之类的东西,我该怎么做?

那么我期望

LIKE '%Test if%it work%'

字符串必须包含“Test if”和“it work”,按此顺序

这是行不通的:

context.SomeTable.Where(s => s.Name.Contains("Test if%it work")).ToList();

如果我使用:

context.SomeTable.Where(s => s.Name.Contains("Test if") && s.Name.Contains("it work")).ToList();

那么我将找到包含“Test if”和“it work”的所有记录,但不是特别按照该顺序

所以对于 Contains 这是不可能的。 但对于 IndexOf 来说确实如此。

IndexOf 将定位搜索字符串并返回它在字符串中的位置。 可以按照正确的顺序找到单词。

-- 更新 --

根据我最初的答案,我的目标不是提供通用解决方案,而是提供另一种不依赖于 sql 的方法的示例。 因此,原始示例仅回答字面问题是正确的。 但由于答案如果是通用的可能会更有用,因此我编写了一个 IQuerable 扩展,它允许向查询添加 like 语句,就像使用 where 语句一样简单。 该扩展适用于 Linq 和 Linq-Sql。

这将按顺序找到所有带有“Test if”和“it work”的记录。

context.SomeTable.Like("test if%it work", "Name").ToList();

listOfString.Like("test if%it work").ToList();

扩展名,允许任意数量的通配符:

/// <summary>
/// Allow to search the string with wildcards.
/// </summary>
/// <typeparam name="T">String or an object with a string member.</typeparam>
/// <param name="q">Original query</param>
/// <param name="searchstring">The searchstring</param>
/// <param name="memberName">The name of the field or null if not a field.</param>
/// <returns>Query filtered by 'LIKE'.</returns>
public static IQueryable<T> Like<T>(this IQueryable<T> q, string searchstring, string memberName = null)
{
    // %a%b%c% --> IndexOf(a) > -1 && IndexOf(b) > IndexOf(a) && IndexOf(c) > IndexOf(b)

    var eParam = Expression.Parameter(typeof(T), "e");

    MethodInfo methodInfo;

    // Linq (C#) is case sensitive, but sql isn't. Use StringComparison ignorecase for Linq.
    // Sql however doesn't know StringComparison, so try to determine the provider.
    var isLinq = (q.Provider.GetType().IsGenericType && q.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>));
    if (isLinq)
        methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) });
    else
        methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });

    Expression expr;
    if (string.IsNullOrEmpty(memberName))
        expr = eParam;
    else
        expr = Expression.Property(eParam, memberName);

    // Split the searchstring by the wildcard symbol:
    var likeParts = searchstring.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries);

    for (int i = 0; i < likeParts.Length; i++)
    {
        MethodCallExpression e;
        if (isLinq)
            e = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) });
        else
            e = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i], typeof(string)));

        if (i == 0)
        {
            // e.IndexOf("likePart") > -1
            q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(e, Expression.Constant(-1, typeof(int))), eParam));
        }
        else
        {
            // e.IndexOf("likePart_previous")
            MethodCallExpression ePrevious;
            if (isLinq)
                ePrevious = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i - 1], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) });
            else
                ePrevious = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i - 1], typeof(string)));

            // e.IndexOf("likePart_previous") < e.IndexOf("likePart")
            q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.LessThan(ePrevious, e), eParam));
        }
    }
    return q;
}

因为它不需要 SqlMethods,我假设您可以将其用于任何数据库,例如 MySql 或 Postgresql。 但我不确定。 我确实使用 Entity Framework 6 使用 Sql Server 对此进行了测试。上述语句在 Sql Server 中生成以下代码。

SELECT [Extent1].* FROM SomeTable AS [Extent1]
WHERE ((( CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) > -1)
AND ((( CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) < 
     (( CAST(CHARINDEX(N'it work', [Extent1].[Name]) AS int)) - 1))

关于性能,似乎有一些关于什么是“更好”的讨论:LIKE 或 CHARINDEX。 从我读到的内容来看,CHARINDEX 似乎是我最喜欢的。

Looking at the question

What if I want something like %Test if%it work%, how do I do it?

then I am expecting something of

LIKE '%Test if%it work%'

meaning that the string must contain 'Test if' and 'it work', in that order.

This will not work:

context.SomeTable.Where(s => s.Name.Contains("Test if%it work")).ToList();

And if I use:

context.SomeTable.Where(s => s.Name.Contains("Test if") && s.Name.Contains("it work")).ToList();

then I will find all records that contain both "Test if" and "it work", but not specifically in that order.

So with Contains this is not possible. But with IndexOf it is.

IndexOf will locate the searchstring AND return the position of it in the string. Making it possible to find the words in the correct order.

-- Update --

With my original answer it was not my goal to provide a generic solution, but rather an example of another approach that is not sql dependend. So it is correct that the original example only answers the literal question. But since the answer may be more useful if it is generic, I've written an IQuerable extension that allows to add a like statement to the query as easy as a where statement. The extension works for both Linq as Linq-Sql.

This will find all records with both "Test if" and "it work", in that order.

context.SomeTable.Like("test if%it work", "Name").ToList();

listOfString.Like("test if%it work").ToList();

Extension, allows any number of wildcards:

/// <summary>
/// Allow to search the string with wildcards.
/// </summary>
/// <typeparam name="T">String or an object with a string member.</typeparam>
/// <param name="q">Original query</param>
/// <param name="searchstring">The searchstring</param>
/// <param name="memberName">The name of the field or null if not a field.</param>
/// <returns>Query filtered by 'LIKE'.</returns>
public static IQueryable<T> Like<T>(this IQueryable<T> q, string searchstring, string memberName = null)
{
    // %a%b%c% --> IndexOf(a) > -1 && IndexOf(b) > IndexOf(a) && IndexOf(c) > IndexOf(b)

    var eParam = Expression.Parameter(typeof(T), "e");

    MethodInfo methodInfo;

    // Linq (C#) is case sensitive, but sql isn't. Use StringComparison ignorecase for Linq.
    // Sql however doesn't know StringComparison, so try to determine the provider.
    var isLinq = (q.Provider.GetType().IsGenericType && q.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>));
    if (isLinq)
        methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) });
    else
        methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });

    Expression expr;
    if (string.IsNullOrEmpty(memberName))
        expr = eParam;
    else
        expr = Expression.Property(eParam, memberName);

    // Split the searchstring by the wildcard symbol:
    var likeParts = searchstring.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries);

    for (int i = 0; i < likeParts.Length; i++)
    {
        MethodCallExpression e;
        if (isLinq)
            e = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) });
        else
            e = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i], typeof(string)));

        if (i == 0)
        {
            // e.IndexOf("likePart") > -1
            q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(e, Expression.Constant(-1, typeof(int))), eParam));
        }
        else
        {
            // e.IndexOf("likePart_previous")
            MethodCallExpression ePrevious;
            if (isLinq)
                ePrevious = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i - 1], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) });
            else
                ePrevious = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i - 1], typeof(string)));

            // e.IndexOf("likePart_previous") < e.IndexOf("likePart")
            q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.LessThan(ePrevious, e), eParam));
        }
    }
    return q;
}

Since it doesn't need SqlMethods I assume you can use this for any database, like MySql or Postgresql. But I do not know for sure. I did test this with Sql Server using Entity Framework 6. The above statement generates the following code in Sql Server.

SELECT [Extent1].* FROM SomeTable AS [Extent1]
WHERE ((( CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) > -1)
AND ((( CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) < 
     (( CAST(CHARINDEX(N'it work', [Extent1].[Name]) AS int)) - 1))

About performance, there seems to be some discussion about what is 'better': LIKE or CHARINDEX. And from what I've read CHARINDEX seems to be favorite.

地狱即天堂 2024-08-01 14:07:38

我知道这是一个老话题,但这是我非常简单的解决方案:

string s=Regex.Escape("pattern - escaped for sanity").Replace("%", ".*").Replace("_", ".?");
user => Regex.IsMatch(user.FullName, s, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

在这段代码中,我使用 SQL 语言的常见转义字符。
如果你想使用*?,转义字符串将相应地包含\*\?,使请务必在 .Replace(...) 语句中包含反斜杠字符。
当然,如果您想让用户能够进行 RexEx 搜索,只需不要转义模式字符串即可。

搜索正则表达式教程以获取其他选项。

我相信通常 % 将匹配至少一个字符,而正则表达式 .* 将匹配零个或多个字符。 所以实际上,%通配符更像是.+(贪婪)而不是.*(惰性)。

希望这可以帮助。

I know this is and old topic, but here is my very simple solution:

string s=Regex.Escape("pattern - escaped for sanity").Replace("%", ".*").Replace("_", ".?");
user => Regex.IsMatch(user.FullName, s, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

In this code, I am using common escape characters for the SQL language.
If you want to use say * and ?, escaped string will contain \* and \? correspondingly, make sure to include the backslash character in the .Replace(...) statement(s).
Of course, if you want to give your user the ability to RexEx search, just don't escape the pattern string.

Search Regex tutorial for other options.

I believe normally % will match at least one character, while the RegEx .* will match zero or more characters. So in reality, the % wildcard is more like .+ (greedy) rather than .* (lazy).

Hope this helps.

紫南 2024-08-01 14:07:38
.Where( column LIKE "Pattern")
.Where( column LIKE "Pattern")
病毒体 2024-08-01 14:07:38
var result = (from x in db.Members
              where x.IDNumber.Contains(idnumber)
              && x.InstitutionIdentifier == institution.Identifier
              select x).ToList();
return result;

适用于 Linq to SQL 和内存中的 Linq。

var result = (from x in db.Members
              where x.IDNumber.Contains(idnumber)
              && x.InstitutionIdentifier == institution.Identifier
              select x).ToList();
return result;

Will work for both Linq to SQL and Linq in memory.

不寐倦长更 2024-08-01 14:07:38

不确定你是在谈论 LinqToSql 还是只是 linq...但你可以像这样的正则表达式:

.Where(dto => System.Text.RegularExpressions.Regex.IsMatch(dto.CustomerName, @"Ad"));

not sure if you talk LinqToSql or just linq... but you could regular expressions like this:

.Where(dto => System.Text.RegularExpressions.Regex.IsMatch(dto.CustomerName, @"Ad"));
你的他你的她 2024-08-01 14:07:38

在包括 LINQ to Objects 的 .Net 代码中,我使用线程 使用 Regex 创建 SQL 的“like”like 函数。

使用示例

bool ret = message.IsSqlLikeMatch(pattern);

更多详细信息请参阅我的帖子
SQL 的“like” .Net 中要比较的模式

In .Net code including LINQ to Objects, I am using implementation of IsSqlLikeMatch function from thread Using Regex to create a SQL's "like" like function..

Example of use

bool ret = message.IsSqlLikeMatch(pattern);

More details in my post
SQL's "like" patterns to compare in .Net

壹場煙雨 2024-08-01 14:07:38

您还可以使用“包含”

var myresult = db.MyItems.Where(x=>x.MyField.Contains(mysearchstring));

You can also use "contains"

var myresult = db.MyItems.Where(x=>x.MyField.Contains(mysearchstring));
任谁 2024-08-01 14:07:38

您说的是 LINQ to object 还是 LINQ to SQL?

对于 LINQ to 对象,您必须求助于正则表达式想。

Are you talking LINQ to objects or LINQ to SQL?

For LINQ to objects you'll have to resort to regular expressions me thinks.

糖果控 2024-08-01 14:07:38

我用它来支持用户搜索中的“*”通配符过滤器。 (顺序无关紧要):

 if (!string.IsNullOrEmpty(SearchString))
    {
     List<String> containValues = new List<String>();
     if (SearchString.Contains("*"))
        {

        String[] pieces = SearchString.Split("*");

        foreach (String piece in pieces)
                {
                if (piece != "")
                   {
                   containValues.Add(piece);
                   }
                 }
           }

       if (containValues.Count > 0)
          {
          foreach(String thisValue in containValues)
             {
             Items = Items.Where(s => s.Description.Contains(thisValue));
             }
           }
           else
           {
           Items = Items.Where(s => s.Description.Contains(SearchString));
           }
       }

I use this for supporting a wildcard filter of "*" in a user's search. (order does not matter):

 if (!string.IsNullOrEmpty(SearchString))
    {
     List<String> containValues = new List<String>();
     if (SearchString.Contains("*"))
        {

        String[] pieces = SearchString.Split("*");

        foreach (String piece in pieces)
                {
                if (piece != "")
                   {
                   containValues.Add(piece);
                   }
                 }
           }

       if (containValues.Count > 0)
          {
          foreach(String thisValue in containValues)
             {
             Items = Items.Where(s => s.Description.Contains(thisValue));
             }
           }
           else
           {
           Items = Items.Where(s => s.Description.Contains(SearchString));
           }
       }
淡淡的优雅 2024-08-01 14:07:38

我扩展了 Ruard van Elburg 的例子来支持我的需求,并认为我会分享。 它处理通配符,例如“a%”(startswith(a))、“%b”(endswith(b))、“a%b”(startswith(a) &&endswith(b))和“a %b%c"(startwith(a)、indexof(a)

    public static class LinqLikeExtension
{
    /// <summary> Permits searching a string value with any number of wildcards. This was written 
    /// to handle a variety of EF wildcard queries not supported because the current version is 
    /// less tan EFv6.2, which has a .Like() method.
    /// like in EFv6.</summary>
    /// <typeparam name="T">String or an object with a string member.</typeparam>
    /// <param name="query">Original query</param>
    /// <param name="searchstring">The searchstring</param>
    /// <param name="columnName">The name of the db column, or null if not a column.</param>
    /// <returns>Query filtered by 'LIKE'.</returns>
    /// <example>return iQueryableRows.Like("a", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("a%", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("%b", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("a%b", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("a%b%c", "ReferenceNumber");</example>
    /// <remarks>Linq (C#) is case sensitive, but sql isn't. Use StringComparison ignorecase for Linq.
    /// Keep in mind that Sql however doesn't know StringComparison, so try to determine the provider.</remarks>
    /// <remarks>base author -- Ruard van Elburg from StackOverflow, modifications by dvn</remarks>
    /// <seealso cref="https://stackoverflow.com/questions/1040380/wildcard-search-for-linq"/>
    public static IQueryable<T> Like<T>(this IQueryable<T> query, string searchstring, string columnName = null)
    {
        var eParam = Expression.Parameter(typeof(T), "e");
        var isLinq = (query.Provider.GetType().IsGenericType && query.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>));

        MethodInfo IndexOf, StartsWith, EndsWith, Equals;
        MethodCallExpression mceCurrent, mcePrevious;

        Expression method = string.IsNullOrEmpty(columnName) ? eParam : (Expression)Expression.Property(eParam, columnName);

        var likeParts = searchstring.Split(new char[] { '%' });

        for (int i = 0; i < likeParts.Length; i++)
        {
            if (likeParts[i] == string.Empty) continue; // "%a"

            if (i == 0)
            {
                if (likeParts.Length == 1) // "a"
                {
                    Equals = isLinq
                        ? Equals = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(StringComparison) })
                        : Equals = typeof(string).GetMethod("Equals", new[] { typeof(string) });
                    mceCurrent = isLinq
                        ? Expression.Call(method, Equals, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                        : Expression.Call(method, Equals, Expression.Constant(likeParts[i], typeof(string)));
                }
                else // "a%" or "a%b"
                {
                    StartsWith = isLinq
                        ? StartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string), typeof(StringComparison) })
                        : StartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
                    mceCurrent = isLinq
                        ? Expression.Call(method, StartsWith, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                        : Expression.Call(method, StartsWith, Expression.Constant(likeParts[i], typeof(string)));
                }
                query = query.Where(Expression.Lambda<Func<T, bool>>(mceCurrent, eParam));
            }
            else if (i == likeParts.Length - 1)  // "a%b" or "%b"
            {
                EndsWith = isLinq
                    ? EndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string), typeof(StringComparison) })
                    : EndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
                mceCurrent = isLinq
                    ? Expression.Call(method, EndsWith, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                    : Expression.Call(method, EndsWith, Expression.Constant(likeParts[i], typeof(string)));
                query = query.Where(Expression.Lambda<Func<T, bool>>(mceCurrent, eParam));
            }
            else // "a%b%c"
            {
                IndexOf = isLinq
                    ? IndexOf = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) })
                    : IndexOf = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });
                mceCurrent = isLinq
                    ? Expression.Call(method, IndexOf, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                    : Expression.Call(method, IndexOf, Expression.Constant(likeParts[i], typeof(string)));
                mcePrevious = isLinq
                    ? Expression.Call(method, IndexOf, new Expression[] { Expression.Constant(likeParts[i - 1], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                    : Expression.Call(method, IndexOf, Expression.Constant(likeParts[i - 1], typeof(string)));
                query = query.Where(Expression.Lambda<Func<T, bool>>(Expression.LessThan(mcePrevious, mceCurrent), eParam));
            }
        }

        return query;
    }
}

我知道这真的很晚了,而且我知道 EFv6.2+ 支持 Like() 方法。 但也许您像我一样,在一家拥有大量遗留应用程序的小商店中,这使得简单地升级 .Net 和 EF 版本变得很困难。

I have extended Ruard van Elburg's example to support my needs, and thought I would share. It handles wildcards such as "a%" (startswith(a)), "%b" (endswith(b)), "a%b" (startswith(a) && endswith(b)), and "a%b%c" (startwith(a), indexof(a) < indexof(b), & endswith(c) ).

    public static class LinqLikeExtension
{
    /// <summary> Permits searching a string value with any number of wildcards. This was written 
    /// to handle a variety of EF wildcard queries not supported because the current version is 
    /// less tan EFv6.2, which has a .Like() method.
    /// like in EFv6.</summary>
    /// <typeparam name="T">String or an object with a string member.</typeparam>
    /// <param name="query">Original query</param>
    /// <param name="searchstring">The searchstring</param>
    /// <param name="columnName">The name of the db column, or null if not a column.</param>
    /// <returns>Query filtered by 'LIKE'.</returns>
    /// <example>return iQueryableRows.Like("a", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("a%", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("%b", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("a%b", "ReferenceNumber");</example>
    /// <example>return iQueryableRows.Like("a%b%c", "ReferenceNumber");</example>
    /// <remarks>Linq (C#) is case sensitive, but sql isn't. Use StringComparison ignorecase for Linq.
    /// Keep in mind that Sql however doesn't know StringComparison, so try to determine the provider.</remarks>
    /// <remarks>base author -- Ruard van Elburg from StackOverflow, modifications by dvn</remarks>
    /// <seealso cref="https://stackoverflow.com/questions/1040380/wildcard-search-for-linq"/>
    public static IQueryable<T> Like<T>(this IQueryable<T> query, string searchstring, string columnName = null)
    {
        var eParam = Expression.Parameter(typeof(T), "e");
        var isLinq = (query.Provider.GetType().IsGenericType && query.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>));

        MethodInfo IndexOf, StartsWith, EndsWith, Equals;
        MethodCallExpression mceCurrent, mcePrevious;

        Expression method = string.IsNullOrEmpty(columnName) ? eParam : (Expression)Expression.Property(eParam, columnName);

        var likeParts = searchstring.Split(new char[] { '%' });

        for (int i = 0; i < likeParts.Length; i++)
        {
            if (likeParts[i] == string.Empty) continue; // "%a"

            if (i == 0)
            {
                if (likeParts.Length == 1) // "a"
                {
                    Equals = isLinq
                        ? Equals = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(StringComparison) })
                        : Equals = typeof(string).GetMethod("Equals", new[] { typeof(string) });
                    mceCurrent = isLinq
                        ? Expression.Call(method, Equals, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                        : Expression.Call(method, Equals, Expression.Constant(likeParts[i], typeof(string)));
                }
                else // "a%" or "a%b"
                {
                    StartsWith = isLinq
                        ? StartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string), typeof(StringComparison) })
                        : StartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
                    mceCurrent = isLinq
                        ? Expression.Call(method, StartsWith, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                        : Expression.Call(method, StartsWith, Expression.Constant(likeParts[i], typeof(string)));
                }
                query = query.Where(Expression.Lambda<Func<T, bool>>(mceCurrent, eParam));
            }
            else if (i == likeParts.Length - 1)  // "a%b" or "%b"
            {
                EndsWith = isLinq
                    ? EndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string), typeof(StringComparison) })
                    : EndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
                mceCurrent = isLinq
                    ? Expression.Call(method, EndsWith, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                    : Expression.Call(method, EndsWith, Expression.Constant(likeParts[i], typeof(string)));
                query = query.Where(Expression.Lambda<Func<T, bool>>(mceCurrent, eParam));
            }
            else // "a%b%c"
            {
                IndexOf = isLinq
                    ? IndexOf = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) })
                    : IndexOf = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });
                mceCurrent = isLinq
                    ? Expression.Call(method, IndexOf, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                    : Expression.Call(method, IndexOf, Expression.Constant(likeParts[i], typeof(string)));
                mcePrevious = isLinq
                    ? Expression.Call(method, IndexOf, new Expression[] { Expression.Constant(likeParts[i - 1], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })
                    : Expression.Call(method, IndexOf, Expression.Constant(likeParts[i - 1], typeof(string)));
                query = query.Where(Expression.Lambda<Func<T, bool>>(Expression.LessThan(mcePrevious, mceCurrent), eParam));
            }
        }

        return query;
    }
}

I understand this is really late, and I understand EFv6.2+ supports a Like() method. But maybe you are like me, in a small shop with large legacy applications that make it difficult to simply upgrade .Net and EF versions.

飘落散花 2024-08-01 14:07:37

您可以使用 SqlMethods.Like()< /a>.

用法示例:

var results =
        from u in users
        where SqlMethods.Like(u.FirstName, "%John%")
        select u;

You can use SqlMethods.Like().

An example of the usage:

var results =
        from u in users
        where SqlMethods.Like(u.FirstName, "%John%")
        select u;
无声情话 2024-08-01 14:07:37

我会使用正则表达式,因为您可能并不总是使用 Linq to SQL。

就像这个 Linq to Objects 的例子

List<string> list = new List<string>();
list.Add("This is a sentence.");
list.Add("This is another one.");
list.Add("C# is fun.");
list.Add("Linq is also fun.");

System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex("This");

var qry = list
    .Where<string>(item => regEx.IsMatch(item))
    .ToList<string>();

// Print results
foreach (var item in qry)
{
    Console.WriteLine(item);
}

I would use Regular Expressions, since you might not always be using Linq to SQL.

Like this example of Linq to Objects

List<string> list = new List<string>();
list.Add("This is a sentence.");
list.Add("This is another one.");
list.Add("C# is fun.");
list.Add("Linq is also fun.");

System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex("This");

var qry = list
    .Where<string>(item => regEx.IsMatch(item))
    .ToList<string>();

// Print results
foreach (var item in qry)
{
    Console.WriteLine(item);
}
鹤舞 2024-08-01 14:07:37

将 System.Data.Linq.SqlClient 添加到您的使用或导入列表中,然后尝试:

var results= from x in data
             where SqlMethods.Like(x.SearchField, “%something%like%this%”)
             select x;

add System.Data.Linq.SqlClient to your using or imports list then try:

var results= from x in data
             where SqlMethods.Like(x.SearchField, “%something%like%this%”)
             select x;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文