2015-10-09 6 views
0

У меня есть Entity, Device, я бы хотел, чтобы пользователь мог искать по всем полям (в идеале все, я бы справился только с текстом). Как я могу это сделать без явного указанияПоиск по всем полям

devices.Where(d => 
    d.prop1.Contains(searchterm) || 
    d.prop2.Contains(searchterm)) 

Это должно произойти в базе данных, но не в возвращаемых объектах.

Редактировать

Я уже попробовал один из комментариев, следующий, который не работал

var stringProperties = typeof(Device) 
    .GetProperties() 
    .Where(prop => prop.PropertyType == deviceSettingValue.GetType()); 
var matches = devices 
    .Where(device => stringProperties.Any(prop => prop.GetValue(device, null) == deviceSettingValue)); 
var fullmatches = matches.ToList(); 

Ошибка

Невозможно создать постоянное значение типа 'System.Reflection.PropertyInfo'. В этом контексте поддерживаются только примитивные типы или перечисление типов .

+1

В своем первом фрагменте кода, вы не значит сделать '||' вместо '' &&? – DavidG

+0

Да, это был псевдо-код, поэтому была сделана ошибка - плохое обновление – Chris

+0

Это может помочь ... http://stackoverflow.com/a/15564970/1663001 – DavidG

ответ

0

Вы можете использовать PropertyType и GetType()

devices.Where(prop => 
prop.PropertyType == query.GetType()) 
0

Найти все свойства класса устройств.

var properties = typeof(Device).GetProperties().Where(prop => prop.PropertyType == query.GetType()); 

затем найти все Устройства, имеющие хотя бы одно свойство со значением, равным запросу.

context.Device.Where(device => properties.Any(prop => prop.GetValue(device, null) == query)); 
+0

Я уже пробовал это, но он не работал из-за 'Невозможно создать постоянное значение типа 'System.Reflection.PropertyInfo'. В этом контексте поддерживаются только примитивные типы или типы перечислений. ' – Chris

1

Вы можете динамически создать выражение на основе свойств объекта, как это:

public IQueryable<T> CreateSearchQuery<T>(DbSet<T> db_set , string value) where T:class 
{ 
    IQueryable<T> query = db_set; 

    List<Expression> expressions = new List<Expression>(); 

    ParameterExpression parameter = Expression.Parameter(typeof (T), "p"); 

    MethodInfo contains_method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 

    foreach (PropertyInfo prop in typeof(T).GetProperties().Where(x => x.PropertyType == typeof (string))) 
    { 
     MemberExpression member_expression = Expression.PropertyOrField(parameter, prop.Name); 

     ConstantExpression value_expression = Expression.Constant(value, typeof(string)); 

     MethodCallExpression contains_expression = Expression.Call(member_expression, contains_method, value_expression); 

     expressions.Add(contains_expression); 
    } 

    if (expressions.Count == 0) 
     return query; 

    Expression or_expression = expressions[0]; 

    for (int i = 1; i < expressions.Count; i++) 
    { 
     or_expression = Expression.OrElse(or_expression, expressions[i]); 
    } 

    Expression<Func<T, bool>> expression = Expression.Lambda<Func<T, bool>>(
     or_expression, parameter); 

    return query.Where(expression); 
} 

Этот метод принимает в DbSet и значение, которое вы хотите найти. Он перебирает свойства, которые имеют тип string, и для каждого свойства он создает выражение «содержит» (например, p => p.Name.Contains("test")).

Затем он объединяет выражения с выражением ИЛИ.

Вы можете использовать этот метод, как это:

var query = CreateSearchQuery(context.Devices, "name"); 

var result = query.ToList();