2016-03-11 3 views
0

мне нужно отфильтровать коллекцию элементов по Проверка наличия значения флага по имени deletion_dateИспользуйте выражение отражения и лямбда с помощью LINQ

public List<T> GetAll() 
{ 
    if (context == null) context = new ajtdevEntities(); 
    return context.Set<T>().Where(p => p.GetType().GetProperty("deletion_date") == null).ToList(); 
} 

я получаю исключение, когда я использовал этот шаблонный метод

LINQ to Entities не распознает метод «System.Reflection.PropertyInfo GetProperty (System.String)», и последний не может быть переведен в хранилище терминов.

Как исправить этот метод?

+0

Не используйте отражение, даже меньше, с привязкой linq-to-entity, которая не поддерживает его. Почему у вас нет метода «GetAllUsers» и «GetAllFoo» и т. Д.? –

ответ

2

Вместо отражения, вы можете построить выражение фильтра вручную с помощью System.Linq.Expressions так:

public List<T> GetAll<T>() 
{ 
    var parameter = Expression.Parameter(typeof(T), "p"); 
    var predicate = Expression.Lambda<Func<T, bool>>(
     Expression.Equal(Expression.PropertyOrField(parameter, "deletion_date"), Expression.Constant(null)), 
     parameter); 
    if (context == null) context = new ajtdevEntities(); 
    return context.Set<T>().Where(predicate).ToList(); 
} 

Обратите внимание, что выше будет бросать исключение, если ваш тип делает не имеет свойства/поля, называемого «deleteion_date», или тип свойства не поддерживает null. Но то же самое можно сказать и о вашей реализации на основе отражения (если это сработало).

2

ORM проверит лямбду и преобразует ее компоненты в SQL. Команда Entity Framework предпочла не поддерживать рефлексию, и это справедливо. Поэтому он не может переводить GetProperty() вызовы SQL, следовательно, вы получите ошибку.

Это не сработает, потому что GetProperty() получает экземпляр PropertyInfo, а не значение. Так, если бы это было null, это означало бы, что тип p не имеет свойства deletion_date.

Правильный путь должен был бы назвать GetValue() на PropertyInfo (обратите внимание, что это будет бросать NullReferenceException если нет свойство с именем константы выглядит):

p => p.GetType().GetProperty("deletion_date").GetValue(p) 

Но опять же, отражение не поддерживается в Entity Framework, поэтому вы хотите использовать интерфейсы:

public interface IDeletable 
{ 
    DateTime? deletion_date { get; set; } 
} 

И примените это к вашему классу или методу в качестве общего ограничения. Затем вы можете использовать его в лямбда:

public class WhateverClass<T> 
    where T : IDeletable 
{ 
    public List<T> GetAll() 
    { 
     return context.Set<T>().Where(p => p.deletion_date == null).ToList(); 
    } 
} 
+0

спасибо. Я не могу реализовать интерфейс 'IDeletable' для всех' T', потому что класс 'T' автогенерируется (из edmx) –

+0

Вы можете, потому что они [сгенерированы как частичные классы] (http: // stackoverflow .com/вопросы/5044596/верстка сущность-рамка орудию-ан-интерфейс). – CodeCaster

+0

Но я должен отредактировать его в каждом повторном поколении модели! –

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