Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ的通配符搜索_C#_Sql_Linq_Wildcard - Fatal编程技术网

C# LINQ的通配符搜索

C# LINQ的通配符搜索,c#,sql,linq,wildcard,C#,Sql,Linq,Wildcard,我想知道是否可以使用LINQ进行通配符搜索 我看到LINQ有Contains、StartsWith、EndsWith等 如果我想要像%Test这样的东西,如果%it工作,我该怎么做 您可以使用的问候语 用法示例如下: var results = from u in users where SqlMethods.Like(u.FirstName, "%John%") select u; 您是在对对象使用LINQ还是对SQL使用LINQ 对于LINQ

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

我看到LINQ有Contains、StartsWith、EndsWith等

如果我想要像%Test这样的东西,如果%it工作,我该怎么做

您可以使用的问候语

用法示例如下:

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

您是在对对象使用LINQ还是对SQL使用LINQ


对于LINQ to对象,您必须求助于我的想法。

不确定您是使用LinqToSql还是仅使用LINQ。。。但您可以使用如下正则表达式:

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

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

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

我会使用正则表达式,因为您可能并不总是使用LINQtoSQL

就像这个Linq到对象的例子一样

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);
}
List List=新列表();
添加(“这是一个句子”);
添加(“这是另一个”);
列表。添加(“C#很有趣。”);
添加(“Linq也很有趣。”);
System.Text.RegularExpressions.Regex Regex=新的System.Text.RegularExpressions.Regex(“此”);
var qry=列表
.Where(item=>regEx.IsMatch(item))
.ToList();
//打印结果
foreach(qry中的var项目)
{
控制台写入线(项目);
}

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

在.Net代码(包括Linq to对象)中,我使用的是来自线程的IsSqlLikeMatch函数的实现

使用示例

bool ret = message.IsSqlLikeMatch(pattern);
更多详情请参阅我的帖子 您也可以使用“包含”


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

string s=Regex.Escape("pattern - escaped for sanity").Replace("%", ".*").Replace("_", ".?");
user => Regex.IsMatch(user.FullName, s, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
在这段代码中,我为SQL语言使用了常见的转义字符。 如果要使用say
*
,转义字符串将相应地包含
\*
\?
,请确保在
语句中包含反斜杠字符。替换(…)
语句。 当然,如果您想让您的用户能够进行RexEx搜索,就不要转义模式字符串

搜索Regex教程中的其他选项

我相信正常情况下,
%
将至少匹配一个字符,而RegEx
*
将匹配零个或多个字符。因此,实际上,
%
通配符更像是
+
(贪婪)而不是
*
(懒惰)


希望这有帮助。

看看这个问题

如果我想要像%Test这样的东西,如果%it工作,我该怎么做

那么我期待着一些

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();
然后,我会找到所有包含“testif”和“it work”的记录,但不是按照那个顺序

因此,这是不可能的。但有了IndexOf它是

IndexOf将定位searchstring并返回它在字符串中的位置。使能按正确的顺序找到单词

--更新--

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

这将按顺序查找所有包含“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;
}
//
///允许使用通配符搜索字符串。
/// 
///字符串或具有字符串成员的对象。
///原始查询
///搜索字符串
///字段的名称,如果不是字段,则为null。
///按“LIKE”筛选的查询。
公共静态IQueryable-Like(此IQueryable q,string searchstring,string memberName=null)
{
//%a%b%c%->IndexOf(a)>-1&&IndexOf(b)>IndexOf(a)&&IndexOf(c)>IndexOf(b)
var eParam=表达式参数(typeof(T),“e”);
方法信息方法信息;
//Linq(C#)区分大小写,但sql不区分大小写。请对Linq使用StringComparison ignorecase。
//但是Sql不知道StringComparison,所以请尝试确定提供程序。
var isLinq=(q.Provider.GetType().IsGenericType&&q.Provider.GetType().GetGenericTypeDefinition()==typeof(EnumerableQuery));
if(isLinq)
methodInfo=typeof(string).GetMethod(“IndexOf”,new[]{typeof(string),typeof(StringComparison)});
其他的
methodInfo=typeof(string).GetMethod(“IndexOf”,new[]{typeof(string)});
表达谱;
if(string.IsNullOrEmpty(memberName))
expr=eParam;
其他的
expr=Expression.Property(eParam,memberName);
//按通配符拆分搜索字符串:
var likeParts=searchstring.Split(新字符[]{“%”,StringSplitOptions.RemoveEmptyEntries);
for(int i=0;i-1
q=q.Where(Expression.Lambda(Expression.GreaterThan(e,Expression.Constant(-1,typeof(int))),eParam));
}
其他的
{
//e.IndexOf(“likePart_previous”)
方法称为前表达;
if(isLinq)
ePrevious=Expression.Call(expr,methodInfo,新表达式[]{Expression.Constant(likeParts[i-1],typeof(string)),Expression.Constant(StringComparison.OrdinalIgnoreCase)});
其他的
ePrevious=Expression.Call(expr,methodInfo,Expression.Constant(likeParts[i-1],typeof(string));
//e.IndexOf(“likePart_previous”)context.SomeTable.Where(s => s.Name.Contains("Test if") && s.Name.Contains("it work")).ToList();
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;
}
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))
var query = from e in _context.Employees
                    where EF.Functions.Like(e.Title, "%developer%")
                    select e;
 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));
           }
       }
    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;
    }
}