복붙노트

[SQL] LINQ를 검색 와일드 카드

SQL

LINQ를 검색 와일드 카드

이 LINQ를 사용하여 검색 와일드 카드 할 수있는 경우에는 내가 알고 싶습니다.

나는 LINQ가 포함되어있다 등 StartsWith, EndsWith 참조

그것은 무엇 %를 일할 %, 내가 그것을 어떻게해야합니까 만약 내가 % 테스트 같은 것을 원한다면?

문안 인사

해결법

  1. ==============================

    1.당신은 항상 SQL에 Linq에를 사용하지 않을 수 있습니다 때부터, 정규 표현식을 사용합니다.

    당신은 항상 SQL에 Linq에를 사용하지 않을 수 있습니다 때부터, 정규 표현식을 사용합니다.

    객체에 대한 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);
    }
    
  2. ==============================

    2.당신은 SqlMethods.Like을 사용할 수 있습니다 ().

    당신은 SqlMethods.Like을 사용할 수 있습니다 ().

    사용의 예 :

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

    3.당신이 사용하거나 수입 한 후 시도 목록에 System.Data.Linq.SqlClient를 추가 :

    당신이 사용하거나 수입 한 후 시도 목록에 System.Data.Linq.SqlClient를 추가 :

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

    4.엔티티 프레임 워크 코어 2.0 (2017 년 8 월 발표) LIKE 연산자가있다 :

    엔티티 프레임 워크 코어 2.0 (2017 년 8 월 발표) LIKE 연산자가있다 :

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

    5.질문을 보면

    질문을 보면

    그때의 일을 기대하고있다

    LIKE '%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();
    

    그때는하지만 특별히 순서로, 그리고 "작동"모두 "만약 테스트"를 포함하는 모든 기록을 찾을 수 있습니다.

    그래서 함께하면이 불가능 들어 있습니다. 그러나 같이 IndexOf와 함께입니다.

    같이 IndexOf는 검색 문장을 찾아 문자열에서의 위치를 ​​반환합니다. 그것을 가능하게하는 것은 올바른 순서로 단어를 찾을 수 있습니다.

    - 업데이트 -

    내 원래의 대답은 일반적인 솔루션이 아니라 SQL dependend 아닌 다른 방법의 예를 제공하기 위해 내 목표 아니었다. 그래서 원래의 예는 문자 그대로의 질문에 대한 대답하는 것이 올바른 것입니다. 대답은 그것이 일반적인 경우 더 유용 할 수 있기 때문에, 나는이 곳에 문으로 쉽게로 쿼리에 같은 문을 추가 할 수있는 IQuerable 확장을 작성했습니다. 확장자는 Linq에-SQL 등 모두 Linq에 작동합니다.

    그 순서 "작동" "경우 테스트"이것은 모두 모든 레코드를 찾을 수 있습니다.

    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을 같은 데이터베이스에 대해이 작업을 사용할 수 있습니다 가정합니다. 그러나 나는 확실히 모른다. 나는 6 위의 문은 SQL Server에서 다음 코드를 생성 엔티티 프레임 워크를 사용하여 SQL 서버와 테스트 이런 짓을.

    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 좋아하는 것 같다.

  6. ==============================

    6.

    .Where( column LIKE "Pattern")
    
  7. ==============================

    7.

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

    메모리에 SQL과 Linq에에 모두 Linq에 대한 작동합니다.

  8. ==============================

    8.나는 이것이 오래된 주제,하지만 여기 내 매우 간단한 해결책을 알고 :

    나는 이것이 오래된 주제,하지만 여기 내 매우 간단한 해결책을 알고 :

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

    이 코드에서, 나는 SQL 언어에 대한 일반적인 이스케이프 문자를 사용하고 있습니다. 당신은 * 사용하고 싶은 말과? 이스케이프 문자열은 \ * \ 포함하고 경우? 대응의 .Replace (...) 문 (들)의 백 슬래시 문자를 포함해야합니다. 물론, 당신은 사용자에게 RexEx 검색 할 수있는 기능을 제공하는 단지 패턴 문자열을 탈출하지합니다.

    다른 옵션에 대한 정규식 자습서를 검색 할 수 있습니다.

    정규식. * 0 개 이상의 문자와 일치합니다 동안 내가 믿는 일반적 %는 적어도 하나의 문자와 일치합니다. 그래서 현실에서, % 와일드 카드. 더 같다 + (욕심)이 아니라. * (게으른).

    도움이 되었기를 바랍니다.

  9. ==============================

    9.하지 당신이 LinqToSql하거나 LINQ 이야기 ...하지만 경우에 수 같은 정규 표현식 :

    하지 당신이 LinqToSql하거나 LINQ 이야기 ...하지만 경우에 수 같은 정규 표현식 :

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

    10.객체에 LINQ를 포함한 닷넷 코드에서, 나는 SQL의 "좋아요"기능 등을 만들 정규식을 사용하여 스레드에서 IsSqlLikeMatch 기능의 구현을 사용하고 있습니다 ..

    객체에 LINQ를 포함한 닷넷 코드에서, 나는 SQL의 "좋아요"기능 등을 만들 정규식을 사용하여 스레드에서 IsSqlLikeMatch 기능의 구현을 사용하고 있습니다 ..

    사용 예

    bool ret = message.IsSqlLikeMatch(pattern);
    

    내 게시물의 자세한 내용 SQL의 닷넷에 비교하는 패턴 "과 같은"

  11. ==============================

    11.당신은 또한 "포함"를 사용할 수 있습니다

    당신은 또한 "포함"를 사용할 수 있습니다

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

    12.당신은 SQL에 개체 또는 LINQ에 LINQ를 이야기하고 있는가?

    당신은 SQL에 개체 또는 LINQ에 LINQ를 이야기하고 있는가?

    개체에 LINQ를 들어 당신이 나를 생각 정규 표현식에 의존해야합니다.

  13. ==============================

    13.나는 사용자의 검색에 "*"와일드 카드 필터를 지원하기 위해 사용합니다. (순서는 중요하지 않습니다)

    나는 사용자의 검색에 "*"와일드 카드 필터를 지원하기 위해 사용합니다. (순서는 중요하지 않습니다)

     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));
               }
           }
    
  14. ==============================

    14.나는 내 요구를 지원하기 위해 Ruard 반 ELBURG의 모범을 확장, 내가 공유하는 것이라고 생각했다. 그것의 "%"(startswith (a)), "%의 B"(endswith (b))의 "%의 B"(startswith (a) && endswith (b))과의 "% B 형 % 와일드 카드 등의 취급 C "(startwith (a) 같이 IndexOf (a) <같이 IndexOf (b), endswith (c)).

    나는 내 요구를 지원하기 위해 Ruard 반 ELBURG의 모범을 확장, 내가 공유하는 것이라고 생각했다. 그것의 "%"(startswith (a)), "%의 B"(endswith (b))의 "%의 B"(startswith (a) && endswith (b))과의 "% 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;
        }
    }
    

    나는이 정말 늦게 이해, 나는 EFv6.2 + 지원에게 같이 () 메소드를 이해합니다. 하지만 어쩌면 당신은 어려운 단순히 닷넷과 EF 버전을 업그레이드 할 수 있도록 큰 기존 응용 프로그램과 작은 가게에서, 나 같은.

  15. from https://stackoverflow.com/questions/1040380/wildcard-search-for-linq by cc-by-sa and MIT license