获取 IQueryable<T>,其中 T 的任何字段包含给定字符串

Gra*_*ler 1 c# linq entity-framework entity-framework-5

我使用的 EF5 有一个由字符串、日期、可为空日期和整数组成的 20 个大型属性实体。是否可以使用 Linq 对每个字段执行包含操作。

我不想为每个字段构建 linq 语句

results = list.Where(house => house.Date1.ToString().Contains(search)||
                              house.Address1.Contains(search)||
                              house.Address2.Contains(search)||
                              house.Address3.Contains(search)||
                              .........................)
Run Code Online (Sandbox Code Playgroud)

我想我想将所有属性转换为字符串(如有必要),然后对每个属性进行包含?理想情况下,这将发生在数据库级别。

我想我无法连接它们,因为如果两个字段的结束和开始创建了搜索文本,可能会导致错误匹配?有任何想法吗?

更新

我目前是这个LINQ string[] 针对多个字段的第二个答案,使用 LinqKit AsExpandable 和 EF 将函数转换为基于类型的字符串。但是我似乎找不到将 DateTime 转换为字符串的 SqlFunction

Ser*_*rvy 5

因此,这里的总体思路是使用PredicateBuilder“或”组合一组表达式,每个表达式代表Contains对给定属性的检查。您可以使用反射来查找给定类型的所有属性以为其创建表达式。

public static Expression<Func<T, bool>> SearchAllFields<T>(string searchText)
{
    var t = Expression.Parameter(typeof(T));
    Expression body = Expression.Constant(false);

    var containsMethod = typeof(string).GetMethod("Contains"
        , new[] { typeof(string) });
    var toStringMethod = typeof(object).GetMethod("ToString");

    var stringProperties = typeof(T).GetProperties()
        .Where(property => property.PropertyType == typeof(string));

    foreach (var property in stringProperties)
    {
        var stringValue = Expression.Call(Expression.Property(t, property.Name),
            toStringMethod);
        var nextExpression = Expression.Call(stringValue,
            containsMethod,
            Expression.Constant(searchText));

        body = Expression.OrElse(body, nextExpression);
    }

    return Expression.Lambda<Func<T, bool>>(body, t);
}
Run Code Online (Sandbox Code Playgroud)