Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用System.Linq.Expressions.Expression根据子级进行筛选?_C#_.net_Linq To Sql_Expression - Fatal编程技术网

C# 如何使用System.Linq.Expressions.Expression根据子级进行筛选?

C# 如何使用System.Linq.Expressions.Expression根据子级进行筛选?,c#,.net,linq-to-sql,expression,C#,.net,Linq To Sql,Expression,我有一个过滤器,可用于多种方法: Expression<Func<Child, bool>> filter = child => child.Status == 1; 其中条件与上述过滤器中的条件相同 我想在这个方法中重用过滤器。但我不知道怎么做。我试过了 return db.Parents.Where(parent => parent.Status == 1 && filt

我有一个过滤器,可用于多种方法:

Expression<Func<Child, bool>> filter = child => child.Status == 1;
其中条件与上述过滤器中的条件相同

我想在这个方法中重用过滤器。但我不知道怎么做。我试过了

return db.Parents.Where(parent => parent.Status == 1 &&
                                  filter(parent.Child));
但是表达式不能用作方法

您可以尝试以下方法:

var compiledFilter = filter.Compile();
foreach (var parent in db.Parents.Where(parent => parent.Status == 1))
    if (compiledFilter(parent.Child))
        yield return parent;
它要求你拉所有的父母,但不像@HugoRune的解决方案,它不需要父母:孩子的1:1关系

由于所涉及的类型不同,我不认为这对您的情况有用,但为了以防万一,下面是一个如何组合
表达式的示例:


编辑:我以前曾建议使用
Compile()
,但在LINQ到SQL之间不起作用。

如果父级和子级之间存在1:1的关系 (不太可能,但示例似乎暗示)然后您可以这样做:

  return db.Parents
  .Where(parent => parent.Status == 1)
  .Select(parent => parent.Child)
  .Where(filter)
  .Select(child=> child.Parent);
否则就很难了

你可以这样做,但这可能是矫枉过正

你可以,但这也很复杂。我自己也没有试过

作为最后一种手段,您当然可以始终调用
yourQuery.AsEnumerable()
,这将导致linq to sql将您的查询转换为sql,并在客户端执行其余工作;然后您就可以编译()表达式了。但是,您失去了linq to sql的性能优势(compile()本身相当慢;每当执行它时,它都会调用JIT编译器):

就我个人而言,我只需定义表达式两次,一次用于child,一次用于parent.child:

   Expression<Func<Child, bool>> filterChild = child => child.Status == 1;
   Expression<Func<Parent, bool>> filterParent = parent => parent.Child.Status == 1;
expressionfilterchild=child=>child.Status==1;
表达式filterParent=parent=>parent.Child.Status==1;

可能不是最优雅的,但可能比其他解决方案更易于维护

public interface IStatus { public int Status { get; set; } }
public class Child : IStatus { }
public class Parent : IStatus
{public Child Child { get; set; }  }

Func<IStatus, bool> filter = (x) => x.Status == 1;
var list = Parents.Where(parent => filter(parent) && filter(parent.Child));
public接口IStatus{public int Status{get;set;}
公共类子类:IStatus{}
公共类父类:IStatus
{public Child{get;set;}}
Func filter=(x)=>x.Status==1;
var list=Parents.Where(parent=>filter(parent)和filter(parent.Child));

希望这有帮助

如果您想要组合表达式,并且仍然能够使用linq to sql,那么您可能需要看一看。它进入表达式内部,并在sql转换之前用其内容替换所有函数调用

这样您就可以直接使用

返回db.Parents
.AsExpandable()
.Where(parent=>parent.Status==1&&filter(parent.Child));

您能否将表达式用作函数

而不是:

Expression<Func<Child, bool>> filter = child => child.Status == 1;

编辑:我误解了这个问题。这是一个糟糕的答案。6年多过去了,我仍然收到一些评论,大意是这不起作用。我不确定,从卫生的角度来看,是否最好删除答案,或者添加此编辑,让答案作为肯定不起作用的示例。我愿意接受这方面的建议。

不需要外部库,也不需要到处乱搞表达式树。相反,编写lambda函数以使用查询链接并利用LINQ的延迟执行

而不是:

expressionfilter=child=>child.Status==1

将其改写为:

Func applyFilterOnParent=query=>query.Where(parent=>parent.Child.Status==1)

Func applyFilterOnChild=query=>query.Where(child=>child.Status==1)

现在,不是:

返回db.Parents.Where(parent=>parent.Status==1&&
过滤器(parent.Child))

你可以写:

var query=db.Parents.AsQueryable();
query=applyFilterOnParent(查询);
返回query.Where(parent=>parent.Status==1)


您还可以在其他LINQ查询中重复使用applyFilter函数。当您希望将lambda函数与LINQ to SQL一起使用时,此技术非常有效,因为LINQ不会将lambda函数转换为SQL。

我认为您无法在LINQ to SQL语句中编译表达式。Lambdas只能在正常情况下工作,很不幸,你似乎是对的。我会建议另一个选项。我想我会使用组合表达式或Dinamic Linq,因为@HugoRune suggestedFunc不适用于Linq to sql,它必须是表达式。由于父类和子类可能是基于db方案自动生成的类,因此给它们一个公共基类并不是那么简单,因为标准实际上是如此简单地共享,这实际上是一个很好的方法:自动生成的类声明为
partial
,这样您就可以在另一个文件中添加接口声明/实现之类的内容。由于您需要使用表达式而不是Func,因此给定的代码无法按原样工作,但您可以使用中所示的方法组合它们。您的解决方案无法转换为SQL。是的,我误解了这个问题。这是一个糟糕的答案。
public interface IStatus { public int Status { get; set; } }
public class Child : IStatus { }
public class Parent : IStatus
{public Child Child { get; set; }  }

Func<IStatus, bool> filter = (x) => x.Status == 1;
var list = Parents.Where(parent => filter(parent) && filter(parent.Child));
Expression<Func<Child, bool>> filter = child => child.Status == 1;
Func<Child, bool> filter = child => child.Status == 1;
return db.Parents.Where(parent => parent.Status == 1 &&
                                  filter(parent.Child));