搜索所有字段

本文关键字:字段 搜索 | 更新日期: 2023-09-27 18:16:50

我有一个实体,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"。只有基本类型或枚举在此上下文中支持类型。

搜索所有字段

您可以根据实体的属性动态构建表达式,如下所示:

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"))。

然后用OR表达式聚合表达式。

你可以这样使用这个方法:

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

可以使用PropertyType和GetType()

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

查找Device类的所有属性

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

然后查找至少有一个属性值等于查询的所有设备。

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