복붙노트

[SQL] LINQ는 (SQL) LIKE 범위 검색을 만들려면

SQL

LINQ는 (SQL) LIKE 범위 검색을 만들려면

나는 도움의 큰 필요, 지금 몇 시간 동안이 일을 시도하고 있어요.

나는이 쿼리가 그래서 :

Select name from BlaBlaBla

order by 

case when name like '9%' then 1 end,
case when name like '8%' then 1 end,
case when name like '7%' then 1 end,
case when name like '6%' then 1 end,
case when name like '5%' then 1 end,
case when name like '4%' then 1 end,
case when name like '3%' then 1 end,
case when name like '2%' then 1 end,
case when name like '1%' then 1 end,
case when name like '0%' then 1 end,

name

그리고 나는 새로운 C #으로 그것을 구현하려는, Asp.Net, 클래스, 내 솔루션에서, 도메인 프로젝트로, 그래서 일부 기능에 대한 OrderType 필터, 것입니다 ...

지금 나는이있다 :

var param = Expression.Parameter(typeof(T), "item");

var paramName = Expression.Property(param, "Name");
var regexMatch = Expression.Constant("^[0-9]");
var startsWithDigit = Expression.Call(typeof(Regex), "IsMatch", 
                                             null, paramName);

var lambda = Expression.Lambda<Func<T, bool>>(startsWithDigit, 
                                              param);

return namesList.OrderBy(lambda)
           .ThenBy(BlaBla1())
           .ThenByDescending(BlaBla2())
           .ThenByDescending(BlaBla3())
           .ThenBy(BlaBla4());

하지만 저에게 말한다, 그 표현은 "IsMatch"방법을 포함하지 않습니다.

저를 도와주세요? 감사합니다!!!

해결법

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

    1.문제는 여기에 정규식을 포함하는 표현이 너무도 당신이 올바른 표현을 구축 성공할 것 때, 당신은 SQL 백엔드에 LINQ에서 사용할 수 없습니다, SQL로 번역 할 수 없다는 것입니다. 트릭이 LINQ는 SQL이 LIKE 문을 포함로 번역하는 것입니다 때문에 그러나, SQL의 LIKE의 방법은 지원은, [0-9]와 같은 와일드 카드를 다양합니다.

    문제는 여기에 정규식을 포함하는 표현이 너무도 당신이 올바른 표현을 구축 성공할 것 때, 당신은 SQL 백엔드에 LINQ에서 사용할 수 없습니다, SQL로 번역 할 수 없다는 것입니다. 트릭이 LINQ는 SQL이 LIKE 문을 포함로 번역하는 것입니다 때문에 그러나, SQL의 LIKE의 방법은 지원은, [0-9]와 같은 와일드 카드를 다양합니다.

    LINQ - 투 - SQL 이벤트 명시 적으로 SQL LIKE 문을 사용할 수있는 가능성을 :

    return namesList.OrderBy(r => SqlMethods.Like(r.Name, "[0-9]%")) ...
    

    이 SqlMethods 클래스는 단지 LINQ - 투 - SQL하지만 사용할 수 있습니다. 엔티티 프레임 워크가 암시 LIKE로 변환 문자열 함수이지만, 그들 중 어느 것도 범위 와일드 카드를 사용하지 ([X-Y). EF에서 성명과 같은 ...

    return namesList.OrderBy(r => r.Name.StartsWith("[0-9]")) ...
    

    ... 넌센스로 번역하는 것입니다 :

    [Name] LIKE '~[0-9]%' ESCAPE '~'
    

    즉 그것은 리터럴 문자열로 시작하는 이름 헛되이 외모 "[0-9]". 그러니 당신이 계속 사용으로 LINQ - 투 - SQL SqlMethods.Like 갈 방법입니다.

    엔티티 프레임 워크 6.1.3 (그리고 낮은)에서 우리는 동일한 결과를 얻기 위해 약간 다른 방식을 사용해야합니다 ...

    return namesList.OrderBy(r => SqlFunctions.PatIndex("[0-9]%", c.Name) == 1) ...
    

    ... SqlFunctions PATINDEX의 범위는 패턴 매칭을 지원하기 때문이다.

    그러나 엔티티 프레임 워크 6.2에서 우리 LINQ - 투 - SQL 때문에 새로운 DbFunctions.Like 기능을 가진 트랙에있어 다시 :

    return namesList.OrderBy(r => DbFunctions.Like(r.Name, "[0-9]%")) ...
    

    마지막으로, 또한 엔티티 프레임 워크의 핵심은 마찬가지로 기능이 있습니다 :

    return namesList.OrderBy(r => EF.Functions.Like(r.Name, "[0-9]%")) ...
    
  2. ==============================

    2.당신은 당신의 순서 부에 대한 사건을 처리하는 방법으로 이런 종류의 샘플을 볼 수 아래.

    당신은 당신의 순서 부에 대한 사건을 처리하는 방법으로 이런 종류의 샘플을 볼 수 아래.

        static void Main(string[] args)
        {
            List<Obvious> list = new List<Obvious>();
            for (int i = 0; i < 100; i++)
            {
                list.Add(new Obvious(i.ToString(), i));
            }
    
            string name = list[30].name;
            switch (name)
            {
                case "9":
                    list.OrderBy(o => o.perc)
                        .ThenByDescending(o => o.name);
                    break;
                default:
                    list.OrderByDescending(o => o.name)
                        .ThenBy(o => o.perc);
                    break;
            }
        }
    
        public class Obvious
        {
            public string name { get; set; }
            public int perc { get; set; }
            public Obvious(string _name, int _perc)
            {
                this.name = _name;
                this.perc = _perc;
            }
    
        }
    
  3. ==============================

    3.내가 당신이라면 나는 복잡성을 많이 제공하기 때문에이 문제를 해결하기 위해 표현식을 사용하려고하지 않을 것입니다.

    내가 당신이라면 나는 복잡성을 많이 제공하기 때문에이 문제를 해결하기 위해 표현식을 사용하려고하지 않을 것입니다.

    나는 당신이 다른 도메인의 개체로 작업 할 수 있도록 일반적인 방법을하고 싶은 것을 볼, 아직 각 개체는 이름 속성이 있음을 예상하고있다. 당신은 이름 속성이 포함 인터페이스를 정의하여 더 간단한 방법으로이 문제를 해결할 수 있습니다. 이 같이 :

        public static void Main()
        {
            var test = new List<YourDomainEntity>()
            {
                new YourDomainEntity() { Name = "1test", OtherProperty = "1"},
                new YourDomainEntity() { Name = "2test",  OtherProperty = "2" },
                new YourDomainEntity() { Name = "2test", OtherProperty = "1"   }
            };
    
            var k = Foo(test).ToList();
        }
    
        public interface INameOrderable
        {
            string Name { get; set; }
        }
    
        public interface IOtherPropertyOrderable
        {
            string OtherProperty { get; set; }
        }
    
        public static IEnumerable<T> Foo<T>(IEnumerable<T> list) where T : INameOrderable, IOtherPropertyOrderable
        {
            return list.OrderBy(a => a.Name, new NamesDescComparer()).ThenBy(b => b.OtherProperty);
        }
    
        public class NamesDescComparer : IComparer<string>
        {
            public int Compare(string x, string y) => -String.CompareOrdinal(x, y);
        }
    
        class YourDomainEntity : INameOrderable, IOtherPropertyOrderable
        {
            public string OtherProperty { get; set; }
            public string Name { get; set; }
        }
    

    나는 방법 푸 당신이 찾고있는 것을 믿습니다.

    여기서 iname 주문 가능한 부분 다음 곳을합니다. 그것은 iname 여기서 주문 가능한 인터페이스를 구현하는 개체에이 방법의 사용을 제한

  4. from https://stackoverflow.com/questions/46952784/how-to-make-linq-execute-a-sql-like-range-search by cc-by-sa and MIT license