Linq에서 SQL Like %를 수행하는 방법은 무엇입니까?


385

Linq로 바꾸려고하는 SQL 절차가 있습니다.

SELECT O.Id, O.Name as Organization
FROM Organizations O
JOIN OrganizationsHierarchy OH ON O.Id=OH.OrganizationsId
where OH.Hierarchy like '%/12/%'

내가 가장 우려하는 라인은 다음과 같습니다.

where OH.Hierarchy like '%/12/%'

예를 들어 / 1 / 3 / 12 /와 같은 계층 구조를 저장하는 열이 있으므로 % / 12 / %를 사용하여 검색하십시오.

내 질문은 Linq 또는 .NET이 백분율 기호를 사용하는 것과 동등한 것입니까?


1
귀하의 질문에 최소한 유사 운영자 태그에 5대한 투표권이 있습니다. sql-like동의어 로 제안하도록 친절하게 요청할 수 있습니까?
커밋

답변:


550
.Where(oh => oh.Hierarchy.Contains("/12/"))

당신은 또한 사용할 수 있습니다 .StartsWith()또는 .EndsWith().


4
StartsWith () 또는 EndsWith ()를 사용하면 쿼리가 발생합니까? 내 말은, 코드가 쿼리로 변환되거나 결과가 DB에서 검색 된 후 객체에서 필터링됩니까?
초보자

5
아니요. StartsWith () 및 EndsWith ()는 조건 자 / 필터의 일부입니다. 실행이 계속 지연됩니다.
andleer

2
NullReferenceException이 발생했습니다 : 객체 참조가 객체의 인스턴스로 설정되지 않았습니다. 따라서 제 경우에는 a.Address1.StartsWith (Address1)이고 a.Address1이 null 일 때 마음에 들지 않습니다
MikeT

11
StartsWith("abc")로 변환됩니다 LIKE 'abc%'EndsWith("abc")에 cnoverted한다LIKE '%abc'
Simon_Weaver

20
왜 문자가있는 유스 케이스에서 작동하지 않았는지 알 수 없었고, 내 어리 석음을 깨달았습니다 ... .ToLower().Contains()사례를 무시하고 싶다면 등을 잊지 마십시오 . 이것이 원하는지 여부는 대소 문자를 구분하지 않는 DB에서 LIKE를 모방 하려는지 여부에 달려 있습니다.
Adam Knights

251

이것을 사용하십시오 :

from c in dc.Organization
where SqlMethods.Like(c.Hierarchy, "%/12/%")
select *;

22
이는 like 명령이 제공하는보다 복잡한 패턴 일치를 사용하려는 경우 실제로 유용합니다. 예를 들어, 12 대신 두 개의 숫자를 확인하려면 다음 식을 사용할 수 있습니다. SqlMethods.Like (c.Hierarchy, "% / [0-9] [0-9] / %") , 이것 좀 봐 msdn.microsoft.com/en-us/library/aa933232(SQL.80).aspx
viggity

고급 사용자가 값 비싼 초기 %를 미리 할당 할 수 있도록하려는 경우에도 매우 유용합니다. StartsWith 또는 Contains를 사용하면 고급 사용자에게 유연성이 제공되지 않습니다.
Simon_Weaver

8
당신은 어떻게 사용합니까 SqlMethods"점 표기법"을 사용하고 계십니까?
dan-gph

12
System.Data.Linq.SqlClient네임 스페이스 를 포함해야 합니다.
johna

1
System.Data.Linq를 추가 할 수 있지만 System.Data.Linq.SqlClient를 찾을 수 없습니다. 더 이상 사용되지 않습니까?
Burak Karakuş

41

Linq-to-SQL *을 사용한다고 가정합니다 (아래 참고 참조). 그렇다면 string.Contains, string.StartsWith 및 string.EndsWith를 사용하여 SQL LIKE 연산자를 사용하는 SQL을 생성하십시오.

from o in dc.Organization
join oh in dc.OrganizationsHierarchy on o.Id equals oh.OrganizationsId
where oh.Hierarchy.Contains(@"/12/")
select new { o.Id, o.Name }

또는

from o in dc.Organization
where o.OrganizationsHierarchy.Hierarchy.Contains(@"/12/")
select new { o.Id, o.Name }

노트 : * = .net 3.5에서 ADO.Net Entity Framework (EF / L2E)를 사용하는 경우 Linq-to-SQL과 동일한 변환을 수행하지 않습니다. L2S는 적절한 변환을 수행하지만 L2E v1 (3.5)은 t-sql 표현식으로 변환되어 where 절 또는 조인 필터에 더 나은 판별 기가없는 경우 쿼리중인 테이블에서 전체 테이블 스캔을 수행합니다.
업데이트 : 이것은 EF / L2E v4 (.net 4.0)에서 수정되었으므로 L2S와 마찬가지로 SQL LIKE를 생성합니다.


@기호로 문자열을 벗어날 필요는 없지만 따라야 할 좋은 규칙 일 수 있습니다.
andleer

27

VB.NET을 사용하는 경우 대답은 "*"입니다. where 절은 다음과 같습니다.

Where OH.Hierarchy Like '*/12/*'

참고 : "*"0 개 이상의 문자와 일치합니다. 다음은 Like 연산자에 대한 msdn 기사입니다 .


VB Like 연산자가 L2S 호출로 변환됩니까? (모르겠어.)
andleerle

8
예, VB Like 연산자는 LINQ 쿼리 표현식에 사용될 때 like의 SQL 버전으로 변환됩니다. 또한 VB Like 연산자는 조회 표현식으로 제한되지 않습니다.
robertz

1
나는 그것이 LINQ 작업 외부에 존재한다는 것을 알았습니다. 좋은 물건. +1
andleer5

9

음 indexOf도 저에게 효과적입니다.

var result = from c in SampleList
where c.LongName.IndexOf(SearchQuery) >= 0
select c;

1
이것이 정답입니다. IndexOf는 SQL에서 CHARINDEX로 변환됩니다. 이것은 LIKE보다 빠를 수 있습니다. 그러나 그 외에도 '% some % thing %'와 같은 검색어를 구성 할 수 있습니다. 'something'은 'thing'앞에 위치해야하는데 Contains로 수행 할 수 없습니다.
Ruard van Elburg

필요한 답변이 8 세이고 허용 된 답변 아래에 여러 계층을 집어 넣었을 때 나는 그것을 좋아합니다. 간단히 말해서 이것은 .Contains (@ "/ 12 /") 및 다른 유사한 답변은 그렇지 않은 반면 작동했습니다. 매우 감사!
IdusOrtus

4

그러한 코드를 사용하십시오

try
{
    using (DatosDataContext dtc = new DatosDataContext())
    {
        var query = from pe in dtc.Personal_Hgo
                    where SqlMethods.Like(pe.nombre, "%" + txtNombre.Text + "%")
                    select new
                    {
                        pe.numero
                        ,
                        pe.nombre
                    };
        dgvDatos.DataSource = query.ToList();
    }
}
catch (Exception ex)
{
    string mensaje = ex.Message;
}

4

.NET 코어는 이제 EF.Functions.Like


이를 사용하여 OP의 문제를 해결하는 방법을 설명 할 수 있습니까?
Robert Columbia

이 SqlMethods.Like 단지 핵심 버전입니다, 예를 LP에서 답을 참조
kofifus

이 답변에는이 기능을 사용하는 방법에 대한 실행 가능한 예제가 포함되어야합니다.
FoxDeploy

3

숫자 문자열과 일치하지 않는 경우 항상 일반적인 경우를 사용하는 것이 좋습니다.

.Where(oh => oh.Hierarchy.ToUpper().Contains(mySearchString.ToUpper()))

2

나는 항상 이것을한다 :

from h in OH
where h.Hierarchy.Contains("/12/")
select h

나는 like 문을 사용하지 않는다는 것을 알고 있지만 백그라운드에서 잘 작동합니다. 이것은 like 문으로 쿼리로 변환됩니다.


답변이 수락 된 답변 (7 년 전에 답변 함) 또는 다른 답변과 어떻게 다릅니 까? 어떤 가치를 더합니까?
David Ferenczy Rogožan

1
@DawidFerenczy이 답변은 "from foo in bar"쿼리 구문으로 작동하지만 허용되는 구문은 그렇지 않습니다.
nasch

1

이것을 시도하십시오, 이것은 나를 위해 잘 작동합니다

from record in context.Organization where record.Hierarchy.Contains(12) select record;


0

포함 은 Linq에서 사용되며 Like 는 SQL에서 사용되는 것과 같습니다 .

string _search="/12/";

. . .

.Where(s => s.Hierarchy.Contains(_search))

Linq에서 다음과 같이 SQL 스크립트를 작성할 수 있습니다.

 var result= Organizations.Join(OrganizationsHierarchy.Where(s=>s.Hierarchy.Contains("/12/")),s=>s.Id,s=>s.OrganizationsId,(org,orgH)=>new {org,orgH});

0

LINQ에서 "SQL Like"메서드를 찾는 방법을 찾는 것처럼 여기에서 텀블러가 발생하는 사람들에게는 매우 효과적인 것이 있습니다.

열 데이터 정렬을 변경하기 위해 데이터베이스를 변경할 수없는 경우입니다. LINQ에서 할 수있는 방법을 찾아야합니다.

도우미 메서드 SqlFunctions.PatIndex마녀를 사용하고 실제 SQL LIKE 연산자와 유사하게 작동합니다.

먼저 검색 값에 가능한 모든 분음 부호 (방금 배운 단어)를 열거하여 다음과 같은 결과를 얻습니다.

déjà     => d[éèêëeÉÈÊËE]j[aàâäAÀÂÄ]
montreal => montr[éèêëeÉÈÊËE][aàâäAÀÂÄ]l
montréal => montr[éèêëeÉÈÊËE][aàâäAÀÂÄ]l

그런 다음 LINQ에서 예를 들면 다음과 같습니다.

var city = "montr[éèêëeÉÈÊËE][aàâäAÀÂÄ]l";
var data = (from loc in _context.Locations
                     where SqlFunctions.PatIndex(city, loc.City) > 0
                     select loc.City).ToList();

그래서 내 필요에 따라 도우미 / 확장 방법을 작성했습니다.

   public static class SqlServerHelper
    {

        private static readonly List<KeyValuePair<string, string>> Diacritics = new List<KeyValuePair<string, string>>()
        {
            new KeyValuePair<string, string>("A", "aàâäAÀÂÄ"),
            new KeyValuePair<string, string>("E", "éèêëeÉÈÊËE"),
            new KeyValuePair<string, string>("U", "uûüùUÛÜÙ"),
            new KeyValuePair<string, string>("C", "cçCÇ"),
            new KeyValuePair<string, string>("I", "iîïIÎÏ"),
            new KeyValuePair<string, string>("O", "ôöÔÖ"),
            new KeyValuePair<string, string>("Y", "YŸÝýyÿ")
        };

        public static string EnumarateDiacritics(this string stringToDiatritics)
        {
            if (string.IsNullOrEmpty(stringToDiatritics.Trim()))
                return stringToDiatritics;

            var diacriticChecked = string.Empty;

            foreach (var c in stringToDiatritics.ToCharArray())
            {
                var diac = Diacritics.FirstOrDefault(o => o.Value.ToCharArray().Contains(c));
                if (string.IsNullOrEmpty(diac.Key))
                    continue;

                //Prevent from doing same letter/Diacritic more than one time
                if (diacriticChecked.Contains(diac.Key))
                    continue;

                diacriticChecked += diac.Key;

                stringToDiatritics = stringToDiatritics.Replace(c.ToString(), "[" + diac.Value + "]");
            }

            stringToDiatritics = "%" + stringToDiatritics + "%";
            return stringToDiatritics;
        }
    }

이 방법을 개선 할 제안이 있으시면 기꺼이 도와 드리겠습니다.


귀하의 예는 기본적으로 집에서 만든 악센트에 둔감 한 데이터 정렬입니다. 한 번은 각각의 모든 쿼리가 필터를 통해 적절한 데이터 정렬이 자동으로 수행 한 작업을 수행하는 프로젝트를 처리해야했습니다. 일반적으로 더 나은 방법은 stackoverflow.com/a/2461550/1736944 를 참조하십시오 . 적절한 것으로 간주되는 데이터베이스, 테이블 및 / 또는 필드에 적절한 데이터 정렬을 지정하십시오. (적절한 데이터 정렬없이 작업하는 것은 순수한 고문입니다)
9Rune5

0

늦었지만 SQL Like 스타일 와일드 카드를 사용하여 문자열 비교를 수행 할 수 있도록 이것을 함께 던졌습니다.

public static class StringLikeExtensions
{
    /// <summary>
    /// Tests a string to be Like another string containing SQL Like style wildcards
    /// </summary>
    /// <param name="value">string to be searched</param>
    /// <param name="searchString">the search string containing wildcards</param>
    /// <returns>value.Like(searchString)</returns>
    /// <example>value.Like("a")</example>
    /// <example>value.Like("a%")</example>
    /// <example>value.Like("%b")</example>
    /// <example>value.Like("a%b")</example>
    /// <example>value.Like("a%b%c")</example>
    /// <remarks>base author -- Ruard van Elburg from StackOverflow, modifications by dvn</remarks>
    /// <remarks>converted to a String extension by sja</remarks>
    /// <seealso cref="/programming/1040380/wildcard-search-for-linq"/>
    public static bool Like(this String value, string searchString)
    {
        bool result = false;

        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"
                {
                    result = value.Equals(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
                else // "a%" or "a%b"
                {
                    result = value.StartsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
            }
            else if (i == likeParts.Length - 1) // "a%b" or "%b"
            {
                result &= value.EndsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
            }
            else // "a%b%c"
            {
                int current = value.IndexOf(likeParts[i], StringComparison.OrdinalIgnoreCase);
                int previous = value.IndexOf(likeParts[i - 1], StringComparison.OrdinalIgnoreCase);
                result &= previous < current;
            }
        }

        return result;
    }

    /// <summary>
    /// Tests a string containing SQL Like style wildcards to be ReverseLike another string 
    /// </summary>
    /// <param name="value">search string containing wildcards</param>
    /// <param name="compareString">string to be compared</param>
    /// <returns>value.ReverseLike(compareString)</returns>
    /// <example>value.ReverseLike("a")</example>
    /// <example>value.ReverseLike("abc")</example>
    /// <example>value.ReverseLike("ab")</example>
    /// <example>value.ReverseLike("axb")</example>
    /// <example>value.ReverseLike("axbyc")</example>
    /// <remarks>reversed logic of Like String extension</remarks>
    public static bool ReverseLike(this String value, string compareString)
    {
        bool result = false;

        var likeParts = value.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"
                {
                    result = compareString.Equals(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
                else // "a%" or "a%b"
                {
                    result = compareString.StartsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
            }
            else if (i == likeParts.Length - 1) // "a%b" or "%b"
            {
                result &= compareString.EndsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
            }
            else // "a%b%c"
            {
                int current = compareString.IndexOf(likeParts[i], StringComparison.OrdinalIgnoreCase);
                int previous = compareString.IndexOf(likeParts[i - 1], StringComparison.OrdinalIgnoreCase);
                result &= previous < current;
            }
        }

        return result;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.