2010-10-06 18 views
25

Mam metodę rozszerzenia do dynamicznego filtrowania wyników Linq do Entities przy użyciu wartości ciągu. Działa dobrze, dopóki nie użyję go do filtrowania zerowych kolumn. Oto mój kod:Praca z typami zerującymi w drzewach wyrażeń

public static IOrderedQueryable<T> OrderingHelperWhere<T>(this IQueryable<T> source, string columnName, object value) 
{ 
    ParameterExpression table = Expression.Parameter(typeof(T), ""); 
    Expression column = Expression.PropertyOrField(table, columnName); 
    Expression where = Expression.GreaterThanOrEqual(column, Expression.Constant(value)); 
    Expression lambda = Expression.Lambda(where, new ParameterExpression[] { table }); 

    Type[] exprArgTypes = { source.ElementType }; 

    MethodCallExpression methodCall = Expression.Call(typeof(Queryable), 
                 "Where", 
                 exprArgTypes, 
                 source.Expression, 
                 lambda); 

    return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(methodCall); 
} 

Oto jak go używać:

var results = (from row in ctx.MyTable select row) 
       .OrderingHelperWhere("userId", 5);//userId is nullable column 

Oto wyjątek Dostaję kiedy używam tego dla pustych kolumn tabeli:

Operator binarny GreaterThanOrEqual nie jest zdefiniowany dla typów "System.Nullable" 1 [System.Int32] "i" System.Int32 "

Nie mogłem tego rozgryźć. Co powinienem zrobić?

+0

możliwy duplikat [Expression.GreaterThan kończy się niepowodzeniem, jeśli perand jest typu zerowego, inne nie są zerowalne] (http://stackoverflow.com/questions/2088231/expression-greaterthan-fails-if-one-operand-is-nullable-type-other-is-non-nulla) – nawfal

Odpowiedz

31

musiałam przekonwertować typ wartości do rodzaju kolumnowej Expression.Convert:..

Expression where = Expression.GreaterThanOrEqual(column, Expression.Convert(Expression.Constant(value), column.Type)); 
+0

Właśnie to robię. Użyłem 'Expression.Constant (value, column.Type)' Powiedział, że mój przypadek jest nieco bardziej skomplikowany, ponieważ wszystkie moje wartości filtru są łańcuchami (nie obiektami, które powinny być typu wymienialnego: int -> int ?, bool -> bool ?, itp.). Potrzebuję więc nie tylko dynamicznego tworzenia wyrażeń, ale także wartości filtrów w typach pasujących do kolumn. – JoeBrockhaus

+1

Po prostu zmieniłem kod, który wcześniej zgłaszał ten błąd. Używanie 'Expression.Convert' było dużo łatwiejsze niż radzenie sobie z sprawdzaniem, czy typ był Nullable (używając odbicia), a jeśli tak, to tworzenie Wyrażenia (jako zwrot z mojej metody pomocnika) z jawnie utworzonym' Nullable <> '). Po prostu rzutuję ciąg znaków na żądany typ wartości (int, bool, itp.), A następnie wyrażenie "Expression.Convert (Expression.Constant (castValue), columnType)". Bum. dzięki za to znalezisko! – JoeBrockhaus

+0

@JoeBrockhaus, dlaczego nie używać tego typu z 'Expresson.Constant', czy jest to zerowalne, czy nie? Rzeczywiście, to właśnie polecam jako odpowiedź tutaj. –

-1

Można sprawdzić, czy typ jest pustych robiąc. If (typeof (T) .equals (typeof (Nullable <>)) wierzę, a następnie przystąpić do obsługi że specjalnie Jeśli można wywołać GetValueOrDefault() metoda jakoś, że będzie działać, lub programmbly utworzyć wartość porównawczą być tego samego typu, a może

HTH