搜索所有字段
本文关键字:字段 搜索 | 更新日期: 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));