2016-12-21 4 views
1

저는 SO 및 다른 웹 사이트에서 여러 스레드를 따라 왔지만 여전히 어려움이 있습니다.Linq 표현식. 문자열보다 큰 것 같습니다.

나는 다음과 같은 코드가 있습니다 : 그것은 작동

lowValue = 2; 
highValue = 11; 

var sampleData = BuildSampleEntityInt(1, 3, 10, 11, 12, 15); 
var query = sampleData.Between(s => s.SampleSearchKey, lowValue, highValue, false); 
Assert.AreEqual(2, query.Count()); 

:

public static IQueryable<TSource> Between<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, TKey low, TKey high, bool inclusive = true) where TKey : IComparable<TKey> 
    { 
     var key = Expression.Invoke(keySelector, keySelector.Parameters.ToArray()); 

     var intLow = int.Parse(low.ToString()); 
     var intHigh = int.Parse(high.ToString()); 

     var lowerBound = (inclusive) 
        ? Expression.GreaterThanOrEqual(key, Expression.Constant(intLow, typeof(int))) 
        : Expression.GreaterThan(key, Expression.Constant(intLow, typeof(int))); 

     var upperBound = (inclusive) 
        ? Expression.LessThanOrEqual(key, Expression.Constant(intHigh, typeof(int))) 
        : Expression.LessThan(key, Expression.Constant(intHigh, typeof(int))); 

     var and = Expression.AndAlso(lowerBound, upperBound); 
     var lambda = Expression.Lambda<Func<TSource, bool>>(
         and, keySelector.Parameters); 

     return source.Where(lambda); 
    } 

나는 다음과 같은 코드를 사용하여이 함수를 호출하는 경우

. 하지만 대신에 같은 문자열을 사용하는 경우 :

lowValueString = "3"; 
highValueString = "10"; 

var sampleData = BuildSampleEntityString(1, 3, 10, 11, 12, 15); 
var query = sampleData.Between(s => s.SampleSearchKey, lowValueString , highValueString); 
Assert.AreEqual(2, query.Count()); 

또는

lowValueString = "3"; 
highValueString = "10"; 
int.TryParse(lowValueString, out lowValue); 
int.TryParse(highValueString, out highValue); 


var sampleData = BuildSampleEntityString(1, 3, 10, 11, 12, 15); 
var query = sampleData.Between(s => s.SampleSearchKey, lowValue, highValue); 
Assert.AreEqual(2, query.Count()); 

나는 다음과 같은 오류 얻을 첫번째 정수로 문자열을 변환 :

{"The binary operator GreaterThanOrEqual is not defined for the types 'System.String' and 'System.Int32'."}

다음 줄이 실행됩니다.

var lowerBound = (inclusive) 
      ? Expression.GreaterThanOrEqual(key, Expression.Constant(intLow, typeof(int))) 
      : Expression.GreaterThan(key, Expression.Constant(intLow, typeof(int))); 

변경할 필요가있는 사람이 있습니까? TSourceTKey을하지만, 실제로는 그 세 가지 유형이있다 : 여기

private IQueryable<SampleEntityInt> BuildSampleEntityInt(params int[] values) 
    { 
     return values.Select(
       value => 
       new SampleEntityInt() { SampleSearchKey = value }).AsQueryable(); 
    } 
+0

덕분에 문제를 발견 ....... 샘플 데이터를 만들 때 두 개의 다른 함수가 사용된다는 것을주의 깊게 살펴 보겠습니다. 하나는 int []를 만들고 다른 하나는 string []을 만듭니다. 그들 모두를 int []로 변경하고 지금은 ok로 변경했습니다. – gilesrpa

+0

이것은 문제를 해결하지 못했습니다. – gilesrpa

+0

간단한 lambdas 대신 표현식으로 빌드하는 이유가 무엇입니까? – MistyK

답변

3

문제는 당신이 두 개의 제네릭 형식 속성을 정의한다는 것입니다 :

나는 다음과 같은 추가했습니다. TKeylowValuehighValue (모두 int이다)와 동일한 유형 인 경우 그것은 작동하지만 lowValuehighValue이 유형 string의이고 TKEY 여전히 int 경우 작동하지 않습니다.

코드는 내가 세 번째 제네릭 매개 변수 TLowHigh를 추가하는 경우, 즉 당신의 저/높이 인수의 유형이다, 작품을 잘 제공 : 모든 사람들이 찾고에 대한

public static IQueryable<TSource> Between<TSource, TKey, TLowHigh>(
     this IQueryable<TSource> source, 
     Expression<Func<TSource, TKey>> keySelector, 
     TLowHigh low, 
     TLowHigh high, 
     bool inclusive = true) 
      where TKey : IComparable<TKey> 
{ 
    var key = Expression.Invoke(keySelector, keySelector.Parameters.ToArray()); 

    var intLow = int.Parse(low.ToString()); 
    var intHigh = int.Parse(high.ToString()); 

    var lowerBound = (inclusive) 
      ? Expression.GreaterThanOrEqual(key, Expression.Constant(intLow, typeof(int))) 
      : Expression.GreaterThan(key, Expression.Constant(intLow, typeof(int))); 

    var upperBound = (inclusive) 
      ? Expression.LessThanOrEqual(key, Expression.Constant(intHigh, typeof(int))) 
      : Expression.LessThan(key, Expression.Constant(intHigh, typeof(int))); 

    var and = Expression.AndAlso(lowerBound, upperBound); 
    var lambda = Expression.Lambda<Func<TSource, bool>>(
        and, keySelector.Parameters); 

    return source.Where(lambda); 
}