有没有一种简单的方法在LINQ to Entities中编写自定义函数?

Man*_*ish 9 c# linq linq-to-entities entity-framework

我正在为我的Entity Framework应用程序编写一个简单的搜索查询.我需要检查一堆字段是否为空,如果没有,请调用它们上的ToLower()并与搜索查询进行比较.LINQ查询看起来像这样:

public IQueryable<Store> SearchStores(string q, IQueryable<Store> source)
{
    q = q.ToLower();

    return (
        from s in source
        where (
            (s.Name != null && s.Name.ToLower().Contains(q)) ||
            (s.Description != null && s.Description.ToLower().Contains(q)) ||
            ...
}
Run Code Online (Sandbox Code Playgroud)

有很多像这样的行,所以我很想写一个帮助方法来清理它:

public static bool SafeSearch(this string s, string q)
{
    return s == null ? false : s.ToLower().Contains(q);
}
Run Code Online (Sandbox Code Playgroud)

这当然不起作用,因为LINQ to实体不理解SafeSearch函数是什么:

LINQ to Entities无法识别方法'Boolean SafeSearch(System.String,System.String)'方法,并且此方法无法转换为商店表达式.

有没有一种简单的方法来编写这样的简单自定义函数?

谢谢!

Nik*_*tov 4

由于 linq 使用的表达式在您实际调用数据库之前不会执行,因此您需要将函数包装在谓词内。

private static Func<Country, bool> Predicate(string q)
{
    return x => (
        q.SafeSearch(x.Name) ||
        q.SafeSearch(x.Description)
        );
}
Run Code Online (Sandbox Code Playgroud)

另外,通过在查询时调用 SafeSearch 扩展方法来反转它,将处理 x.Name 为 null 的情况。

public static class SearchExt
{
    public static bool SafeSearch(this string q, string param)
    {
        return param == null ? false : param.ToLower().Contains(q);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以将它与扩展方法一起使用

return source.Where(Predicate(q));
Run Code Online (Sandbox Code Playgroud)

或者使用 linq 表达式

return from p in source
       where Predicate(q).Invoke(p)
       select p;
Run Code Online (Sandbox Code Playgroud)