2014-01-28 3 views
0

У меня есть сетка Kendo, в которой включена фильтрация сервера. Поле для фильтрации через передается как строка. Например, я хочу отфильтровать «SampleId». Теперь мне нужно написать запрос LINQ to Entities, который может фильтроваться с использованием строго типизированного свойства SampleId. Например:LINQ to Entities - Адресация свойств класса с их именами строк

db.Cases.Where(x=>targetlist.Contains(x.SampleId)) 

где targetlist - это список элементов из фильтра.

Таким образом, существует ли способ написать запрос, чтобы «SampleId» мог напрямую перевести на Case.SampleId?

Я попытался отразить и использовал GetProperty и GetValue, а LINQ to Entities не нравится.

Любые предложения будут высоко оценены!


EDIT (ПИД- для оригинального плаката srinaik2020):

@zaitsman: это код размещен в комментарии ниже и фактическое решение проблемы, на основе принятого ответа.

public static class MyExtensions 
{ 
    public static string GetPropertyByName(this CaseV case1, string name) 
    { 
     var x = typeof (CaseV).GetProperty(name).GetValue(case1); 

     if (x != null) 
     { 
      return x.ToString(); 
     } else { 
      return "none"; 
     } 
    } 
} 
+1

вся * точка * использовать что-то вроде EF является * избегать * делать подобные вещи. * Идея * заключается в том, чтобы скомпилировать тип времени. Если вы этого не хотите, просто не используйте всю функцию и возвращайтесь к более традиционному методу параметризованных запросов, выписанных как строки. – Servy

ответ

0

Вы можете использовать метод расширения и прикрепить его к классу.

Этот метод должен использовать отражение для извлечения свойства из объекта.

Вот указатели:

После того, как это работает, вы хотите просто установить и/или получить значение свойства. Метод GetProperty() выше просто возвращает объект PropertyInfo. Чтобы получить или установить значение, вам необходимо будет использовать соответствующие методы PropertyInfo.

Я бы не выставил PropertyInfo, потому что это было бы руины волшебство.

Лучше должен методы расширения, то:

T GetPropertyByName<T>(string name); 
SetPropertyByName<T>(string name, T value); 
+0

Спасибо! Добавление метода расширения и вызов его поддерживает LINQ to Entity. –

+0

@ srinaik2020 У вас есть образец того, что сработало для вас? – zaitsman

+0

@zaitsman Не уверен, что самое лучшее место для размещения кода ... так что просто вставьте его здесь ... Дайте мне знать, если вы ищете что-то еще. 'public static class MyExtensions { Публичная статическая строка GetPropertyByName (этот случай Case1, имя строки) { var x = typeof (CaseV) .GetProperty (name) .GetValue (case1); if (x! = Null) return x.ToString(); else return "none"; } } ' –

0

если вы хотите выражение, вы можете использовать их, чтобы получить значение свойства как так (взято из некоторых помощников я сделал в LINQPad поэтому может не может быть полный код):

public static class Helper { 

    public static IEnumerable<T> Select<T>(this IEnumerable enumerable, string memberName) { 
     IQueryable queryable = enumerable.AsQueryable(); 
     LambdaExpression expression = PredicateFor(queryable.ElementType, memberName); 
     return CreateQuery(queryable, "Select", new[] { expression.ReturnType }, expression).Cast<T>(); 
    } 

    public static MemberExpression NestedPropertyOrField(this Expression expression, string nestedPropertyOrFieldName) { 
     MemberExpression e; 

     if (nestedPropertyOrFieldName.IndexOf('.') >= 0) { 
      var split = nestedPropertyOrFieldName.Split(new[] { '.' }, 2, StringSplitOptions.RemoveEmptyEntries); 

      if (split.Length > 0) { 
       e = Expression.PropertyOrField(expression, split[0]); 

       if (split.Length > 1) { 
        e = NestedPropertyOrField(e, split[1]); 
       } 
      } else { 
       throw new ArgumentException("'" + nestedPropertyOrFieldName + "' is not a member of type '" + expression.Type.AssemblyQualifiedName + "'"); 
      } 
     } else { 
      e = Expression.PropertyOrField(expression, nestedPropertyOrFieldName); 
     } 

     return e; 
    } 

    private static IEnumerable CreateQuery(IEnumerable enumerable, string method, Type[] typeArguments, params Expression[] arguments) { 
     IQueryable queryable = enumerable.AsQueryable(); 
     Type[] typeArgs = new[] { queryable.ElementType }.Concat(typeArguments ?? new Type[ 0 ]).ToArray(); 
     Expression[] args = new[] { queryable.Expression }.Concat(arguments ?? new Expression[ 0 ]).ToArray(); 
     MethodCallExpression methodCallExpression = Expression.Call(typeof(Queryable), method, typeArgs, args); 
     return queryable.Provider.CreateQuery(methodCallExpression); 
    } 

    internal static LambdaExpression PredicateFor(Type elementType, string memberName) { 
     var pe = Expression.Parameter(elementType, "@item"); 
     Expression expression = pe; 

     if (memberName.StartsWith("@item", StringComparison.OrdinalIgnoreCase)) { 
      memberName = memberName.Substring(5); 
     } 

     if (memberName.Length > 0) 
      expression = NestedPropertyOrField(expression, memberName); 

     var delegateType = Expression.GetFuncType(elementType, expression.Type); 
     return Expression.Lambda(delegateType, expression, new[] {pe}); 
    } 
} 

, а затем сделать

string propertyName = // get property name from somewhere, ie: "SomeObject.NestedProperty.ID" 
db.Cases.Select<string>(propertyName).Where(targetlist.Contains); 
+0

Если вы хотите вызвать метод на' IQueryable', просто вызовите его на 'IQueryable', не нужно его вызывать в' IEnumerable' и пытаться его преобразовать. Это больше работает над вами и подразумевает, что вызывающий пользователь будет выполнять работу в LINQ с объектами. – Servy

+0

Это сделано так, что один метод может обрабатывать IQueryable, ITable, DbSet, IEnumerable и т. Д. – dariusc

+0

@DariusL. Я предполагаю, что OP хочет только это (часть, которую вы пропустили) 'string propertyName = // получить имя свойства откуда-то». Получение имени свойства из строго типизированного свойства –

Смежные вопросы