2011-09-28 8 views
0

현실 세계의 문제 해결하려고하는 전화 번호가 많은 데이터베이스가 문자열로 저장됩니다 (예 : "(02) 9971 1209"). . 내 프로그램 사용자는 전화 번호를 입력하기 시작할 것이며 입력 할 때 "입력 시작"작업을 사용하여 입력 한 내용을 보냈고 데이터베이스의 전화 번호 목록을 필터링하는 데 사용됩니다.람다 식을 표현식 트리로 변환

사용자가 "02997"을 입력하면 번호가 대괄호로 묶인 위치 코드와 함께 저장되므로 아무 것도 맞지 않습니다. . 작업이 작업을 위해서는, 사용자는이 좋지 않다 '('입력하여 모든 검색을 시작해야 할 것입니다

TL;. 박사 버전은 질문의 하단에 내가했다

.

class Program 
{ 
    static string [] phones = {"(02) 9489 3048","(04) 1128 2148","(01) 9971 1208",}; 

    static void Main(string[] args) 
    { 
     for (;;) 
     { 
      Console.WriteLine("Enter your number: "); 
      string input = Console.ReadLine(); 

      Func<string, string> strip = 
      tehstring => tehstring.Where(x => char.IsDigit(x)) 
            .Aggregate("", (x, y) => x + y); 
      var results = phones.Where(z => strip(z).StartsWith(strip(input))); 

      foreach (var x in results) 
       Console.WriteLine(x); 
     } 
    } 
} 

이것은이다 : 그것에서 문제가 실제 상황과 내가 같은 조건에서 대규모 코드베이스의 산만하지 않고 집중할 수 작고 밀폐 된 솔루션으로의, 내 솔루션은 일부 LINQ의 trickiness을 할 수 있었다 모든 선한 일, 완벽하게 일하는 것, 내가 필요한 것을 정확하게 해줍니다. xt : 표현식 트리로 변환해야하기 때문에 구현해야하는 코드베이스로 다시 포팅 할 수 없습니다.

나는 그것을 아래로 괴짜해야 할 코드 :

static Expression GetOperationExpression(
    StringFilterOperation operation, 
    Expression propertyExpression, 
    Expression valueExpression) 
{ 
    switch (operation) 
    { 
    case StringFilterOperation.StartsWith: 
    var startsWith = typeof(string) 
        .GetMethod("StartsWith", new Type[] { typeof(string) }); 
    Contract.Assume(startsWith != null); 
    return Expression.Call(propertyExpression, startsWith, valueExpression); 
    //etc etc etc 

내가 propertyExpression을해야하고, 어떻게 든 (외부 DB에이 경우 전화 번호의 테이블)가 얘기하는 속성을 포함 내 람다 함수에서. 그런 다음 모든 것을 다시 Expression Tree로 디 컴파일하여 반환해야합니다.

그게 내가 붙어있어. 난 여전히 문제가 해결되지 않는 이런 일을하고 싶어

Expression<Func<string[],string, IEnumerable<string>>> expr = 
(db, uinput) => db.Where(z => z.Where(x => char.IsDigit(x)) 
           .Aggregate("", (x, y) => x + y) 
           .StartsWith(uinput.Where(x => char.IsDigit(x)) 
               .Aggregate("",(x,y) => x + y))); 

: 내가 가지고 올 수있는 최선의도 어쨌든 적당한 유형이없는 LINQ의 슈퍼 길고 우아 라인이다 약간 희미하다 :

Expression<Func<string, string>> strip = 
tehstring => tehstring.Where(x => char.IsDigit(x)) 
         .Aggregate("", (x, y) => x + y); 
Expression<Func<string, string, string>> query = 
(db, uinput) => db.Where(z => strip(z) 
        .StartsWith(strip(uinput))); 

나는 약간의 변경을 많이 시도했지만 컴파일을 거부했다.

TL; DR :

길고도 짧은 이야기, 내가 무엇을하지만,과, 데이터베이스에 테이블에 필드를 나타내는 식을 가지고 같은 일을 나타내는 하나에 그 표현을 변환하기 만하면됩니다 숫자가 아닌 모든 문자를 제거하는 필터가 적용됩니다.

답변

5

스트립 된 전화 번호를 가져 오는 데 사용할 많은 표현식이 LINQ 공급자에 의해 지원되지 않을 수 있습니다.

개인적으로 모든 전화 번호가 잘린 형식으로 표시되는 데이터베이스보기를 제안합니다. 그런 다음 해당보기에 대해 표준 StartsWith 쿼리를 수행 할 수 있습니다.

+1

오른쪽, 특히'char.IsDigit'는 없습니다. –

+0

나는 이것이 사실일지도 모른다고 걱정했다. 나는 여전히 전화 번호의 형식을 변경하는 것은 아무 일도하지 않으므로 어쨌든 linq 공급자를 사용하려고합니다. – TheIronKnuckle

+0

@TheIronKnuckle : 또 다른 옵션은 데이터베이스에서 사용자 정의 함수를 만들고 linq 쿼리 내에서 호출하는 것입니다. 어느 쪽이든, LINQ to SQL 또는 LINQ to Entities로 구현 된 메서드를 사용하여 묻는 것을 수행 할 수있는 방법을 생각할 수 없기 때문에 데이터베이스에서 무언가를 만들어야합니다. 다시 말해, 이것을 컴파일해도 런타임에 예외가 발생합니다. – StriplingWarrior

관련 문제