创建一个共同的谓词函数(Creating a common predicate function)

2019-07-03 12:00发布

首先,我不知道什么条件使用问这个问题,这可能是为什么我还没有找到一个答案,从搜索自己。

所以我使用LINQ工作,SQL(C#,.NET 4中),我想匹配的标准,其中我会做这样的事情的基础,所有用户的列表:

var users = DataContext.Users.Where(x => x.Criteria1 == "something");

但在这种情况下,有一些领域我想匹配,事情是这些特定领域是一种常见的检查,我希望能够创建,我可以使用内的任何我的用户查询来检查这个专功能比赛。

要尝试并解释说,好一点的可以举一个例子:比方说,用户有5面旗帜,我希望有一个共同的检查,看看是否这些标志的设置。 所以,我可以写我的查询,如下所示:

var users = DataContext.Users.Where(x => x.Flag1 || x.Flag2 || x.Flag3 || x.Flag4 || x.Flag5);

但我想这样做是单独指出,“5标志检查”这样我就可以在其他查​​询中使用它太,最终我想用这样的:

var users = DataContext.Users.Where(x => x.Criteria1 == "something" && CheckForFlags(x));

我已经有这样的功能,尝试这样做:

static bool CheckForFlags(User user)
{
   return user.Flag1 || user.Flag2 || user.Flag3 || user.Flag4 || user.Flag5;
}

但我得到一个错误:

“方法‘布尔CheckForFlags(用户)’没有支持转换为SQL。”

......这是有道理的,但它有什么我可以做,以使这项工作,我希望它的方式? 或者,这是SQL限制,因为我使用LINQ实际上是在东西会使用LINQ工作对象?

Answer 1:

有关的LINQ to SQL如何处理表达式的整洁的事情是,你实际上可以在你的代码的其他地方打造出来的表情和在查询中引用它们。 你为什么不尝试是这样的:

public static class Predicates
{
    public static Expression<Func<User, bool>> CheckForFlags()
    {
        return (user => user.Flag1 || user.Flag2 || user.Flag3 ||
                        user.Flag4 || user.Flag5);
    }

    public static Expression<Func<User, bool>> CheckForCriteria(string value)
    {
        return (user => user.Criteria1 == value);
    }
}

一旦你有你的谓词定义的,它很容易在查询中使用它们。

var users = DataContext.Users
    .Where(Predicates.CheckForFlags())
    .Where(Predicates.CheckForCriteria("something"));


Answer 2:

您是否尝试过PredicateBuilder? 我没有用它在一年多了,但是写“或者”查询时,我发现它有效。

http://www.albahari.com/nutshell/predicatebuilder.aspx

从页面的一个例子:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where (predicate);
}


Answer 3:

据我所知有两种可能的方式来做到这一点。

快速正简单的方法是过滤搜索结果的SQL执行后,像这样的东西:

var users = DataContext.Users.Where(x => x.Criteria1 == "something");
    .ToEnumerable()
    .Where(x => CheckForFlags(x));

然而,这是在性能方面非常差。 这将只从数据库匹配的第一准则返回所有行,然后在客户端上筛选内存中的结果。 功能,但是从最佳远。

第二, 更高性能的选择是创建数据库本身上的UDF和LINQ调用它。 例如,见这个问题 。 最明显的缺点是,它的代码移动到数据库中,这是任何一个喜欢做的(对于很多正当的理由)。

这里很可能是其他可行的解决方案,但这些是仅有的两个我知道的。



Answer 4:

认为这会工作,我我已经用它在我的LINQ到SQL的项目,但我不能找到一个例子副手。 如果没有,让我知道。


而不是创建一个功能,创建一个新的属性对Users对象:

partial class Users {
   bool CheckForFlags
    {
       get { 
          return Flag1 || Flag2 || Flag3 || Flag4 || Flag5;
       }
    }
}

那么你应该能够做到

var users = DataContext.Users.Where(x => x.CheckForFlags);


Answer 5:

就像你说的,这是有限制的,因为你是使用LINQ to SQL。

这样的事情应该工作,虽然:

var users = DataContext.Users.Where(x => x.Criteria1 == "something")
                             .ToArray()
                             .Where(x => CheckForFlags(x));


文章来源: Creating a common predicate function